Skip to content

Commit c36797c

Browse files
Merge pull request gcc-mirror#72 from iains/contracts-nonattr-location-improvements
Contracts nonattr location improvements
2 parents c3699ec + 108128d commit c36797c

File tree

5 files changed

+66
-28
lines changed

5 files changed

+66
-28
lines changed

gcc/cp/contracts.cc

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -847,7 +847,7 @@ finish_contract_attribute (tree identifier, tree contract)
847847
if any. */
848848

849849
void
850-
update_late_contract (tree contract, tree result, tree condition)
850+
update_late_contract (tree contract, tree result, cp_expr condition)
851851
{
852852
if (TREE_CODE (contract) == POSTCONDITION_STMT)
853853
POSTCONDITION_IDENTIFIER (contract) = result;
@@ -2691,18 +2691,26 @@ remap_and_emit_conditions (tree fn, tree condfn, tree_code code)
26912691
tree
26922692
finish_contract_condition (cp_expr condition)
26932693
{
2694+
if (!condition || error_operand_p (condition))
2695+
return condition;
2696+
26942697
/* Ensure we have the condition location saved in case we later need to
26952698
emit a conversion error during template instantiation and wouldn't
2696-
otherwise have it. */
2697-
if (!CAN_HAVE_LOCATION_P (condition) || EXCEPTIONAL_CLASS_P (condition))
2698-
{
2699-
condition = build1_loc (condition.get_location (), VIEW_CONVERT_EXPR,
2699+
otherwise have it. This differs from maybe_wrap_with_location in that
2700+
it allows wrappers on EXCEPTIONAL_CLASS_P which includes CONSTRUCTORs. */
2701+
if (!CAN_HAVE_LOCATION_P (condition)
2702+
&& condition.get_location () != UNKNOWN_LOCATION)
2703+
{
2704+
tree_code code
2705+
= (((CONSTANT_CLASS_P (condition) && TREE_CODE (condition) != STRING_CST)
2706+
|| (TREE_CODE (condition) == CONST_DECL && !TREE_STATIC (condition)))
2707+
? NON_LVALUE_EXPR : VIEW_CONVERT_EXPR);
2708+
condition = build1_loc (condition.get_location (), code,
27002709
TREE_TYPE (condition), condition);
27012710
EXPR_LOCATION_WRAPPER_P (condition) = true;
27022711
}
27032712

2704-
if (condition == error_mark_node
2705-
|| type_dependent_expression_p (condition))
2713+
if (type_dependent_expression_p (condition))
27062714
return condition;
27072715

27082716
return condition_conversion (condition);
@@ -2841,17 +2849,24 @@ start_function_contracts (tree fndecl)
28412849
if (POSTCONDITION_P (CONTRACT_STATEMENT (ca)))
28422850
if (tree id = POSTCONDITION_IDENTIFIER (CONTRACT_STATEMENT (ca)))
28432851
{
2852+
tree r_name = tree_strip_any_location_wrapper (id);
28442853
if (TREE_CODE (id) == PARM_DECL)
2845-
id = DECL_NAME (id);
2846-
gcc_checking_assert (id && TREE_CODE (id) == IDENTIFIER_NODE);
2847-
tree seen = lookup_name (id);
2854+
r_name = DECL_NAME (id);
2855+
gcc_checking_assert (r_name && TREE_CODE (r_name) == IDENTIFIER_NODE);
2856+
tree seen = lookup_name (r_name);
28482857
if (seen
28492858
&& TREE_CODE (seen) == PARM_DECL
28502859
&& DECL_CONTEXT (seen)
28512860
&& DECL_CONTEXT (seen) == fndecl)
28522861
{
28532862
auto_diagnostic_group d;
2854-
error_at (EXPR_LOCATION (CONTRACT_STATEMENT (ca)),
2863+
location_t id_l = location_wrapper_p (id)
2864+
? EXPR_LOCATION (id)
2865+
: DECL_SOURCE_LOCATION (id);
2866+
location_t co_l = EXPR_LOCATION (CONTRACT_STATEMENT (ca));
2867+
if (id_l != UNKNOWN_LOCATION)
2868+
co_l = make_location (id_l, get_start (co_l), get_finish (co_l));
2869+
error_at (co_l,
28552870
"contract postcondition result names must not shadow"
28562871
" function parameters");
28572872
inform (DECL_SOURCE_LOCATION (seen),

gcc/cp/contracts.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -334,7 +334,6 @@ extern void defer_guarded_contract_match (tree, tree, tree);
334334
extern bool diagnose_misapplied_contracts (tree);
335335
extern tree finish_contract_attribute (tree, tree);
336336
extern tree invalidate_contract (tree);
337-
extern void update_late_contract (tree, tree, tree);
338337
extern tree splice_out_contracts (tree);
339338
extern bool all_attributes_are_contracts_p (tree);
340339
extern void copy_and_remap_contracts (tree, tree, bool, bool);

gcc/cp/cp-tree.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8916,6 +8916,7 @@ extern tree make_postcondition_variable (cp_expr);
89168916
extern tree make_postcondition_variable (cp_expr, tree);
89178917
extern tree grok_contract (tree, tree, tree, cp_expr, location_t);
89188918
extern tree finish_contract_condition (cp_expr);
8919+
extern void update_late_contract (tree, tree, cp_expr);
89198920
extern tree constify_contract_access (tree);
89208921
extern bool maybe_reject_param_in_postcondition (tree);
89218922

gcc/cp/parser.cc

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -31490,6 +31490,8 @@ cp_parser_contract_attribute_spec (cp_parser *parser, tree attribute,
3149031490
/*consume_paren=*/false);
3149131491

3149231492
cp_token *last = cp_lexer_peek_token (parser->lexer);
31493+
location_t end = last->location;
31494+
loc = make_location (loc, loc, end);
3149331495

3149431496
if (!attr_mode)
3149531497
parens.require_close (parser);
@@ -31500,6 +31502,8 @@ cp_parser_contract_attribute_spec (cp_parser *parser, tree attribute,
3150031502
DEFPARSE_INSTANTIATIONS (condition) = NULL;
3150131503

3150231504
/* And its corresponding contract. */
31505+
if (identifier)
31506+
identifier.maybe_add_location_wrapper ();
3150331507
contract = grok_contract (attribute, mode, identifier, condition, loc);
3150431508
}
3150531509
else
@@ -31541,6 +31545,13 @@ cp_parser_contract_attribute_spec (cp_parser *parser, tree attribute,
3154131545
/* Revert (any) constification of the current class object. */
3154231546
current_class_ref = current_class_ref_copy;
3154331547

31548+
if (contract != error_mark_node)
31549+
{
31550+
location_t end = cp_lexer_peek_token (parser->lexer)->location;
31551+
loc = make_location (loc, loc, end);
31552+
SET_EXPR_LOCATION (contract, loc);
31553+
}
31554+
3154431555
/* For natural syntax, we eat the parens here. For the attribute
3154531556
syntax, it will be done one level up, we just need to skip to it. */
3154631557
if (!attr_mode)
@@ -31579,16 +31590,19 @@ void cp_parser_late_contract_condition (cp_parser *parser,
3157931590
if (TREE_CODE (condition) != DEFERRED_PARSE)
3158031591
return;
3158131592

31582-
tree identifier = NULL_TREE;
31593+
tree r_ident = NULL_TREE;
3158331594
if (TREE_CODE (contract) == POSTCONDITION_STMT)
31584-
identifier = POSTCONDITION_IDENTIFIER (contract);
31595+
r_ident = POSTCONDITION_IDENTIFIER (contract);
3158531596

3158631597
tree type = TREE_TYPE (TREE_TYPE (fn));
31587-
if (identifier)
31598+
location_t r_loc = UNKNOWN_LOCATION;
31599+
if (r_ident)
3158831600
{
31589-
/* TODO: Can we guarantee that the identifier has a location? */
31590-
location_t loc = cp_expr_location (contract);
31591-
if (!check_postcondition_result (fn, type, loc))
31601+
r_loc = EXPR_LOCATION (r_ident);
31602+
r_ident = tree_strip_any_location_wrapper (r_ident);
31603+
if (r_loc == UNKNOWN_LOCATION)
31604+
r_loc = cp_expr_location (contract);
31605+
if (!check_postcondition_result (fn, type, r_loc))
3159231606
{
3159331607
invalidate_contract (contract);
3159431608
return;
@@ -31640,16 +31654,17 @@ void cp_parser_late_contract_condition (cp_parser *parser,
3164031654
should_constify_contract = should_constify;
3164131655
/* Build a fake variable for the result identifier. */
3164231656
tree result = NULL_TREE;
31643-
if (identifier)
31657+
if (r_ident)
3164431658
{
31645-
result = make_postcondition_variable (identifier, type);
31659+
cp_expr result_id (r_ident, r_loc);
31660+
result = make_postcondition_variable (result_id, type);
3164631661
++processing_template_decl;
3164731662
}
31648-
condition = cp_parser_conditional_expression (parser);
31663+
cp_expr parsed_condition = cp_parser_conditional_expression (parser);
3164931664
/* Commit to changes. */
31650-
update_late_contract (contract, result, condition);
31665+
update_late_contract (contract, result, parsed_condition);
3165131666
/* Leave our temporary scope for the postcondition result. */
31652-
if (identifier)
31667+
if (r_ident)
3165331668
--processing_template_decl;
3165431669
processing_postcondition = old_pc;
3165531670
should_constify_contract = old_const;

gcc/cp/pt.cc

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12057,11 +12057,19 @@ tsubst_contract (tree decl, tree t, tree args, tsubst_flags_t complain,
1205712057
/* Make the variable available for lookup. */
1205812058
register_local_specialization (newvar, oldvar);
1205912059

12060-
CONTRACT_CONDITION (r)
12061-
= tsubst_expr (CONTRACT_CONDITION (t), args, complain, in_decl);
12062-
12063-
/* The condition is converted to bool. */
12064-
CONTRACT_CONDITION (r) = finish_contract_condition (CONTRACT_CONDITION (r));
12060+
/* Contract conditions have a wider application of location wrappers than
12061+
other trees which will not work with the generic handling in tsubst_expr,
12062+
remove the wrapper here... */
12063+
location_t cond_l = EXPR_LOCATION (CONTRACT_CONDITION (t));
12064+
tree cond_t = tree_strip_any_location_wrapper (CONTRACT_CONDITION (t));
12065+
12066+
/* ... and substitute with the contained expression. */
12067+
cond_t = tsubst_expr (cond_t, args, complain, in_decl);
12068+
12069+
/* Converted to bool, if possible, and then re-apply a location wrapper
12070+
when required. */
12071+
cp_expr new_condition (cond_t, cond_l);
12072+
CONTRACT_CONDITION (r) = finish_contract_condition (new_condition);
1206512073

1206612074
/* And the comment. */
1206712075
/* TODO : this does not do anything at the moment. The CONTRACT_COMMENT is

0 commit comments

Comments
 (0)