@@ -13150,19 +13150,17 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr,
1315013150
1315113151 parens.require_close (parser);
1315213152 /* Build the contract. */
13153- tree contract = grok_contract (cont_assert, NULL_TREE /*mode*/,
13154- NULL_TREE /*result*/, condition, loc);
13155- if (contract != error_mark_node && !modifier.error_p)
13156- {
13157- set_contract_mutable (contract, modifier.mutable_p);
13158- set_contract_const (contract, modifier.const_p);
13159- }
13153+ tree contract
13154+ = grok_contract (cont_assert, /*mode*/NULL_TREE,
13155+ /*result*/NULL_TREE, condition, loc);
13156+ if (contract != error_mark_node)
13157+ set_contract_const (contract, should_constify);
1316013158
1316113159 std_attrs = finish_contract_attribute (cont_assert, contract);
1316213160
1316313161 /* If there are errors in the contract, we do not create the
13164- attribute tree. This assumes no attributes on
13165- 'contract_assert' */
13162+ attribute tree. This assumes no attributes on
13163+ 'contract_assert'. */
1316613164 if (std_attrs == error_mark_node)
1316713165 std_attrs = NULL_TREE;
1316813166 else if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
@@ -31317,27 +31315,40 @@ cp_parser_contract_attribute_spec (cp_parser *parser, tree attribute,
3131731315 if (attr_mode || identifier)
3131831316 cp_parser_require (parser, CPP_COLON, RT_COLON);
3131931317
31320- /* Defer the parsing of pre/post contracts inside class definitions. */
31318+ bool should_constify = false;
31319+ /* When we have P2900 semantics in force.
31320+ Do we have an override for const-ification? This applies equally to
31321+ deferred or immediate parses. */
31322+ if (flag_contracts_nonattr)
31323+ {
31324+ should_constify = !flag_contracts_nonattr_noconst;
31325+ if (!modifier.error_p
31326+ && (modifier.mutable_p
31327+ || (flag_contracts_nonattr_const_keyword && !modifier.const_p)))
31328+ should_constify = false;
31329+ }
31330+
3132131331 tree contract;
3132231332 if (!assertion_p &&
3132331333 current_class_type &&
3132431334 TYPE_BEING_DEFINED (current_class_type))
3132531335 {
31326- /* Skip until we reach an unenclose ']'. If we ran into an unnested ']'
31327- that doesn't close the attribute, return an error and let the attribute
31328- handling code emit an error for missing ']]'. */
31336+ /* Defer the parsing of pre/post contracts inside class definitions. */
3132931337 cp_token *first = cp_lexer_peek_token (parser->lexer);
3133031338 if (attr_mode)
3133131339 {
31340+ /* Skip until we reach a closing token ]. */
3133231341 cp_parser_skip_to_closing_parenthesis_1 (parser,
3133331342 /*recovering=*/false,
3133431343 CPP_CLOSE_SQUARE,
3133531344 /*consume_paren=*/false);
3133631345 if (cp_lexer_peek_token (parser->lexer)->type != CPP_CLOSE_SQUARE
3133731346 || cp_lexer_peek_nth_token (parser->lexer, 2)->type != CPP_CLOSE_SQUARE)
3133831347 return error_mark_node;
31348+ /* Otherwise the closing ]] will be consumed by the caller. */
3133931349 }
3134031350 else
31351+ /* Skip until we reach a closing token ). */
3134131352 cp_parser_skip_to_closing_parenthesis_1 (parser,
3134231353 /*recovering=*/false,
3134331354 CPP_CLOSE_PAREN,
@@ -31371,19 +31382,13 @@ cp_parser_contract_attribute_spec (cp_parser *parser, tree attribute,
3137131382 }
3137231383
3137331384 bool old_flag_contracts_nonattr_noconst = flag_contracts_nonattr_noconst;
31374-
31375- /* Do we have an override for const-ification? */
31376- bool should_constify = !flag_contracts_nonattr_noconst;
31377- if (!modifier.error_p
31378- && (modifier.mutable_p
31379- || (flag_contracts_nonattr_const_keyword && !modifier.const_p)))
31380- should_constify = false;
31385+ /* The should_constify value should account for all the mixed flags. */
3138131386 flag_contracts_nonattr_noconst = !should_constify;
3138231387
3138331388 /* If we have a current class object, see if we need to consider
3138431389 it const when processing the contract condition. */
3138531390 tree current_class_ref_copy = current_class_ref;
31386- if (flag_contracts_nonattr && should_constify && current_class_ref_copy)
31391+ if (should_constify && current_class_ref_copy)
3138731392 current_class_ref = view_as_const (current_class_ref_copy);
3138831393
3138931394 /* Parse the condition, ensuring that parameters or the return variable
@@ -31425,21 +31430,9 @@ cp_parser_contract_attribute_spec (cp_parser *parser, tree attribute,
3142531430 return error_mark_node;
3142631431 }
3142731432
31433+ /* Save the decision about const-ification. */
3142831434 if (contract != error_mark_node)
31429- {
31430- set_contract_mutable (contract, false);
31431- set_contract_const (contract, false);
31432- if (flag_contracts_nonattr && !attr_mode)
31433- {
31434- if (!modifier.error_p)
31435- {
31436- set_contract_mutable (contract, modifier.mutable_p);
31437- set_contract_const (contract, modifier.const_p);
31438- }
31439- else
31440- set_contract_const (contract, !flag_contracts_nonattr_noconst);
31441- }
31442- }
31435+ set_contract_const (contract, should_constify);
3144331436
3144431437 return finish_contract_attribute (attribute, contract);
3144531438}
@@ -31480,15 +31473,7 @@ void cp_parser_late_contract_condition (cp_parser *parser,
3148031473 ++processing_template_decl;
3148131474 }
3148231475
31483- bool mutable_p = get_contract_mutable (contract);
31484- bool const_p = get_contract_const (contract);
31485- bool old_flag_contracts_nonattr_noconst = flag_contracts_nonattr_noconst;
31486- if (flag_contracts_nonattr
31487- && (mutable_p
31488- || (flag_contracts_nonattr_const_keyword && !const_p)))
31489- flag_contracts_nonattr_noconst = true;
31490-
31491- /* In C++"0 contracts, 'this' is not allowed in preconditions of
31476+ /* In C++20 contracts, 'this' is not allowed in preconditions of
3149231477 constructors or in postconditions of destructors. Note that the
3149331478 previous value of this variable is established by the calling function,
3149431479 so we need to save it here. P2900 contracts allow access to members
@@ -31509,22 +31494,21 @@ void cp_parser_late_contract_condition (cp_parser *parser,
3150931494 }
3151031495 }
3151131496 else
31512- {
31513- contract_class_ptr = NULL_TREE;
31514- }
31497+ contract_class_ptr = NULL_TREE;
3151531498
3151631499 push_unparsed_function_queues (parser);
3151731500
3151831501 /* Push the saved tokens onto the parser's lexer stack. */
3151931502 cp_token_cache *tokens = DEFPARSE_TOKENS (condition);
3152031503 cp_parser_push_lexer_for_tokens (parser, tokens);
3152131504
31522- /* if we have a current class object, constify it before processing
31523- * the contract condition */
31524- if (flag_contracts_nonattr
31525- && !flag_contracts_nonattr_noconst
31526- && current_class_ref)
31527- current_class_ref = view_as_const (current_class_ref);
31505+ bool old_flag_contracts_nonattr_noconst = flag_contracts_nonattr_noconst;
31506+ bool should_constify = get_contract_const (contract);
31507+ /* If we have a current class object, see if we need to consider
31508+ it const when processing the contract condition. */
31509+ tree current_class_ref_copy = current_class_ref;
31510+ if (should_constify && current_class_ref_copy)
31511+ current_class_ref = view_as_const (current_class_ref_copy);
3152831512
3152931513 /* Parse the condition, ensuring that parameters or the return variable
3153031514 aren't flagged for use outside the body of a function. */
0 commit comments