Skip to content

Commit 178e18d

Browse files
Merge pull request gcc-mirror#63 from iains/contracts-nonattr-revise-handling-of-constify
c++, contracts: Revise handling of const-ification.
2 parents 2de979e + 996b8d8 commit 178e18d

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
@@ -8942,36 +8942,20 @@ set_contract_semantic (tree t, contract_semantic semantic)
89428942
TREE_LANG_FLAG_0 (t) = (semantic & 0x04) >> 2;
89438943
}
89448944

8945-
/* Returns the mutable flag of the node. */
8945+
/* Returns the const-ify flag of the node. */
89468946

8947-
inline int
8948-
get_contract_mutable (const_tree t)
8949-
{
8950-
return TREE_LANG_FLAG_4 (CONTRACT_CHECK (t));
8951-
}
8952-
8953-
/* Sets the mutable flag of the node. */
8954-
8955-
inline void
8956-
set_contract_mutable (tree t, int mut)
8957-
{
8958-
TREE_LANG_FLAG_4 (CONTRACT_CHECK (t)) = mut;
8959-
}
8960-
8961-
/* Returns the mutable flag of the node. */
8962-
8963-
inline int
8947+
inline bool
89648948
get_contract_const (const_tree t)
89658949
{
8966-
return TREE_LANG_FLAG_5 (CONTRACT_CHECK (t));
8950+
return TREE_LANG_FLAG_4 (CONTRACT_CHECK (t));
89678951
}
89688952

8969-
/* Sets the mutable flag of the node. */
8953+
/* Sets the const-ify flag of the node. */
89708954

89718955
inline void
8972-
set_contract_const (tree t, int mut)
8956+
set_contract_const (tree t, bool constify)
89738957
{
8974-
TREE_LANG_FLAG_5 (CONTRACT_CHECK (t)) = mut;
8958+
TREE_LANG_FLAG_4 (CONTRACT_CHECK (t)) = constify;
89758959
}
89768960

89778961
/* Inline bodies. */

gcc/cp/parser.cc

Lines changed: 37 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -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. */

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)