Skip to content

Commit c6f0494

Browse files
committed
c++, contracts: Revise handling of const-ification.
This: 1. Revises the handling so that we only need to preserve a single tree flag which denotes the requirement to const-ify the contract content. 2. Uses the saved flag instead of recomputing the condition in delayed parses and template substitution. Signed-off-by: Iain Sandoe <[email protected]>
1 parent a768dbc commit c6f0494

File tree

3 files changed

+44
-82
lines changed

3 files changed

+44
-82
lines changed

gcc/cp/cp-tree.h

Lines changed: 6 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -8947,36 +8947,20 @@ set_contract_semantic (tree t, contract_semantic semantic)
89478947
TREE_LANG_FLAG_0 (t) = (semantic & 0x04) >> 2;
89488948
}
89498949

8950-
/* Returns the mutable flag of the node. */
8950+
/* Returns the const-ify flag of the node. */
89518951

8952-
inline int
8953-
get_contract_mutable (const_tree t)
8954-
{
8955-
return TREE_LANG_FLAG_4 (CONTRACT_CHECK (t));
8956-
}
8957-
8958-
/* Sets the mutable flag of the node. */
8959-
8960-
inline void
8961-
set_contract_mutable (tree t, int mut)
8962-
{
8963-
TREE_LANG_FLAG_4 (CONTRACT_CHECK (t)) = mut;
8964-
}
8965-
8966-
/* Returns the mutable flag of the node. */
8967-
8968-
inline int
8952+
inline bool
89698953
get_contract_const (const_tree t)
89708954
{
8971-
return TREE_LANG_FLAG_5 (CONTRACT_CHECK (t));
8955+
return TREE_LANG_FLAG_4 (CONTRACT_CHECK (t));
89728956
}
89738957

8974-
/* Sets the mutable flag of the node. */
8958+
/* Sets the const-ify flag of the node. */
89758959

89768960
inline void
8977-
set_contract_const (tree t, int mut)
8961+
set_contract_const (tree t, bool constify)
89788962
{
8979-
TREE_LANG_FLAG_5 (CONTRACT_CHECK (t)) = mut;
8963+
TREE_LANG_FLAG_4 (CONTRACT_CHECK (t)) = constify;
89808964
}
89818965

89828966
/* Inline bodies. */

gcc/cp/parser.cc

Lines changed: 37 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -13249,19 +13249,17 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr,
1324913249

1325013250
parens.require_close (parser);
1325113251
/* Build the contract. */
13252-
tree contract = grok_contract (cont_assert, NULL_TREE /*mode*/,
13253-
NULL_TREE /*result*/, condition, loc);
13254-
if (contract != error_mark_node && !modifier.error_p)
13255-
{
13256-
set_contract_mutable (contract, modifier.mutable_p);
13257-
set_contract_const (contract, modifier.const_p);
13258-
}
13252+
tree contract
13253+
= grok_contract (cont_assert, /*mode*/NULL_TREE,
13254+
/*result*/NULL_TREE, condition, loc);
13255+
if (contract != error_mark_node)
13256+
set_contract_const (contract, should_constify);
1325913257

1326013258
std_attrs = finish_contract_attribute (cont_assert, contract);
1326113259

1326213260
/* If there are errors in the contract, we do not create the
13263-
attribute tree. This assumes no attributes on
13264-
'contract_assert' */
13261+
attribute tree. This assumes no attributes on
13262+
'contract_assert'. */
1326513263
if (std_attrs == error_mark_node)
1326613264
std_attrs = NULL_TREE;
1326713265
else if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
@@ -31448,27 +31446,40 @@ cp_parser_contract_attribute_spec (cp_parser *parser, tree attribute,
3144831446
if (attr_mode || identifier)
3144931447
cp_parser_require (parser, CPP_COLON, RT_COLON);
3145031448

31451-
/* Defer the parsing of pre/post contracts inside class definitions. */
31449+
bool should_constify = false;
31450+
/* When we have P2900 semantics in force.
31451+
Do we have an override for const-ification? This applies equally to
31452+
deferred or immediate parses. */
31453+
if (flag_contracts_nonattr)
31454+
{
31455+
should_constify = !flag_contracts_nonattr_noconst;
31456+
if (!modifier.error_p
31457+
&& (modifier.mutable_p
31458+
|| (flag_contracts_nonattr_const_keyword && !modifier.const_p)))
31459+
should_constify = false;
31460+
}
31461+
3145231462
tree contract;
3145331463
if (!assertion_p &&
3145431464
current_class_type &&
3145531465
TYPE_BEING_DEFINED (current_class_type))
3145631466
{
31457-
/* Skip until we reach an unenclose ']'. If we ran into an unnested ']'
31458-
that doesn't close the attribute, return an error and let the attribute
31459-
handling code emit an error for missing ']]'. */
31467+
/* Defer the parsing of pre/post contracts inside class definitions. */
3146031468
cp_token *first = cp_lexer_peek_token (parser->lexer);
3146131469
if (attr_mode)
3146231470
{
31471+
/* Skip until we reach a closing token ]. */
3146331472
cp_parser_skip_to_closing_parenthesis_1 (parser,
3146431473
/*recovering=*/false,
3146531474
CPP_CLOSE_SQUARE,
3146631475
/*consume_paren=*/false);
3146731476
if (cp_lexer_peek_token (parser->lexer)->type != CPP_CLOSE_SQUARE
3146831477
|| cp_lexer_peek_nth_token (parser->lexer, 2)->type != CPP_CLOSE_SQUARE)
3146931478
return error_mark_node;
31479+
/* Otherwise the closing ]] will be consumed by the caller. */
3147031480
}
3147131481
else
31482+
/* Skip until we reach a closing token ). */
3147231483
cp_parser_skip_to_closing_parenthesis_1 (parser,
3147331484
/*recovering=*/false,
3147431485
CPP_CLOSE_PAREN,
@@ -31502,19 +31513,13 @@ cp_parser_contract_attribute_spec (cp_parser *parser, tree attribute,
3150231513
}
3150331514

3150431515
bool old_flag_contracts_nonattr_noconst = flag_contracts_nonattr_noconst;
31505-
31506-
/* Do we have an override for const-ification? */
31507-
bool should_constify = !flag_contracts_nonattr_noconst;
31508-
if (!modifier.error_p
31509-
&& (modifier.mutable_p
31510-
|| (flag_contracts_nonattr_const_keyword && !modifier.const_p)))
31511-
should_constify = false;
31516+
/* The should_constify value should account for all the mixed flags. */
3151231517
flag_contracts_nonattr_noconst = !should_constify;
3151331518

3151431519
/* If we have a current class object, see if we need to consider
3151531520
it const when processing the contract condition. */
3151631521
tree current_class_ref_copy = current_class_ref;
31517-
if (flag_contracts_nonattr && should_constify && current_class_ref_copy)
31522+
if (should_constify && current_class_ref_copy)
3151831523
current_class_ref = view_as_const (current_class_ref_copy);
3151931524

3152031525
/* Parse the condition, ensuring that parameters or the return variable
@@ -31556,21 +31561,9 @@ cp_parser_contract_attribute_spec (cp_parser *parser, tree attribute,
3155631561
return error_mark_node;
3155731562
}
3155831563

31564+
/* Save the decision about const-ification. */
3155931565
if (contract != error_mark_node)
31560-
{
31561-
set_contract_mutable (contract, false);
31562-
set_contract_const (contract, false);
31563-
if (flag_contracts_nonattr && !attr_mode)
31564-
{
31565-
if (!modifier.error_p)
31566-
{
31567-
set_contract_mutable (contract, modifier.mutable_p);
31568-
set_contract_const (contract, modifier.const_p);
31569-
}
31570-
else
31571-
set_contract_const (contract, !flag_contracts_nonattr_noconst);
31572-
}
31573-
}
31566+
set_contract_const (contract, should_constify);
3157431567

3157531568
return finish_contract_attribute (attribute, contract);
3157631569
}
@@ -31611,15 +31604,7 @@ void cp_parser_late_contract_condition (cp_parser *parser,
3161131604
++processing_template_decl;
3161231605
}
3161331606

31614-
bool mutable_p = get_contract_mutable (contract);
31615-
bool const_p = get_contract_const (contract);
31616-
bool old_flag_contracts_nonattr_noconst = flag_contracts_nonattr_noconst;
31617-
if (flag_contracts_nonattr
31618-
&& (mutable_p
31619-
|| (flag_contracts_nonattr_const_keyword && !const_p)))
31620-
flag_contracts_nonattr_noconst = true;
31621-
31622-
/* In C++"0 contracts, 'this' is not allowed in preconditions of
31607+
/* In C++20 contracts, 'this' is not allowed in preconditions of
3162331608
constructors or in postconditions of destructors. Note that the
3162431609
previous value of this variable is established by the calling function,
3162531610
so we need to save it here. P2900 contracts allow access to members
@@ -31640,22 +31625,21 @@ void cp_parser_late_contract_condition (cp_parser *parser,
3164031625
}
3164131626
}
3164231627
else
31643-
{
31644-
contract_class_ptr = NULL_TREE;
31645-
}
31628+
contract_class_ptr = NULL_TREE;
3164631629

3164731630
push_unparsed_function_queues (parser);
3164831631

3164931632
/* Push the saved tokens onto the parser's lexer stack. */
3165031633
cp_token_cache *tokens = DEFPARSE_TOKENS (condition);
3165131634
cp_parser_push_lexer_for_tokens (parser, tokens);
3165231635

31653-
/* if we have a current class object, constify it before processing
31654-
* the contract condition */
31655-
if (flag_contracts_nonattr
31656-
&& !flag_contracts_nonattr_noconst
31657-
&& current_class_ref)
31658-
current_class_ref = view_as_const (current_class_ref);
31636+
bool old_flag_contracts_nonattr_noconst = flag_contracts_nonattr_noconst;
31637+
bool should_constify = get_contract_const (contract);
31638+
/* If we have a current class object, see if we need to consider
31639+
it const when processing the contract condition. */
31640+
tree current_class_ref_copy = current_class_ref;
31641+
if (should_constify && current_class_ref_copy)
31642+
current_class_ref = view_as_const (current_class_ref_copy);
3165931643

3166031644
/* Parse the condition, ensuring that parameters or the return variable
3166131645
aren't flagged for use outside the body of a function. */

gcc/cp/pt.cc

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12047,15 +12047,9 @@ tsubst_contract (tree decl, tree t, tree args, tsubst_flags_t complain,
1204712047

1204812048
/* Instantiate the condition. If the return type is undeduced, process
1204912049
the expression as if inside a template to avoid spurious type errors. */
12050-
bool mutable_p = get_contract_mutable (t);
1205112050
bool const_p = get_contract_const (t);
1205212051
bool old_flag_contracts_nonattr_noconst = flag_contracts_nonattr_noconst;
12053-
if (flag_contracts_nonattr && flag_contracts_nonattr_mutable_keyword &&
12054-
mutable_p)
12055-
flag_contracts_nonattr_noconst = 1;
12056-
if (flag_contracts_nonattr && flag_contracts_nonattr_const_keyword &&
12057-
!const_p)
12058-
flag_contracts_nonattr_noconst = 1;
12052+
flag_contracts_nonattr_noconst = !const_p;
1205912053

1206012054
if (auto_p)
1206112055
++processing_template_decl;

0 commit comments

Comments
 (0)