Skip to content

Commit

Permalink
Merge pull request #10 from NinaRanns/contracts-nonattr
Browse files Browse the repository at this point in the history
pr113968 and minor natural syntax parsing fix
  • Loading branch information
villevoutilainen authored Jul 3, 2024
2 parents e7ce892 + 032d1d1 commit 5d5df29
Show file tree
Hide file tree
Showing 5 changed files with 77 additions and 8 deletions.
8 changes: 8 additions & 0 deletions gcc/cp/contracts.cc
Original file line number Diff line number Diff line change
Expand Up @@ -697,6 +697,10 @@ tree
grok_contract (tree attribute, tree mode, tree result, cp_expr condition,
location_t loc)
{

if (condition == error_mark_node)
return error_mark_node;

tree_code code;
if (is_attribute_p ("assert", attribute) || is_attribute_p ("contract_assert", attribute))
code = ASSERTION_STMT;
Expand Down Expand Up @@ -732,6 +736,10 @@ grok_contract (tree attribute, tree mode, tree result, cp_expr condition,

/* The condition is converted to bool. */
condition = finish_contract_condition (condition);

if (condition == error_mark_node)
return error_mark_node;

CONTRACT_CONDITION (contract) = condition;

return contract;
Expand Down
15 changes: 12 additions & 3 deletions gcc/cp/parser.cc
Original file line number Diff line number Diff line change
Expand Up @@ -12834,9 +12834,14 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr,
/* Build the contract. */
tree contract = grok_contract (cont_assert, NULL_TREE /*mode*/,
NULL_TREE /*result*/, condition, loc);
std_attrs = finish_contract_attribute (cont_assert, contract);

std_attrs = finish_contract_attribute (cont_assert, contract);

// If there are errors in the contract, we do not create
// the attribute tree. This assumes no attributes on
// 'contract_assert'
if (std_attrs == error_mark_node)
std_attrs = NULL_TREE;
}
else
error_at (
Expand Down Expand Up @@ -30881,13 +30886,14 @@ cp_parser_contract_attribute_spec (cp_parser *parser, tree attribute,
cp_expr condition = cp_parser_conditional_expression (parser);
--processing_contract_condition;

/* For natural syntax, we eat the parens here. For the attribute syntax,
it will be done one level up, we just need to skip to it. */
if (!attr_mode)
parens.require_close (parser);

/* Try to recover from errors by scanning up to the end of the
attribute. Sometimes we get partially parsed expressions, so
we need to search the condition for errors. */
if (contains_error_p (condition))
else if (contains_error_p (condition))
cp_parser_skip_up_to_closing_square_bracket (parser);

/* Build the contract. */
Expand All @@ -30907,6 +30913,9 @@ cp_parser_contract_attribute_spec (cp_parser *parser, tree attribute,
return error_mark_node;
}

if (contract == error_mark_node)
return error_mark_node;

return finish_contract_attribute (attribute, contract);
}

Expand Down
10 changes: 5 additions & 5 deletions gcc/testsuite/g++.dg/contracts/new/contract-assert_err.C
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,13 @@ void contract_assert(); // { dg-error "expected unqualified-id before" }
int main()
{

contract_assert(x==0); // { dg-error ".x. was not declared in this scope"}
contract_assert int i = 0; // // { dg-error "expected primary-expression before|before .int." }
contract_assert(x==0); // { dg-error ".x. was not declared in this scope"}
contract_assert int i = 0; // // { dg-error "expected primary-expression before|before .int." }

i = 7;
[[assert: i == 0]] contract_assert(x==0); // { dg-error "assertions must be followed by" }
i = 7;
[[assert: i == 0]] contract_assert(x==0); // { dg-error "assertions must be followed by" }

contract_assert( x = 0); // { dg-error "expected primary-expression before|expected .\\). before .=. token" }
contract_assert( x = 0); // { dg-error "expected primary-expression before|expected .\\). before .=. token" }

contract_assert( y == 0); // { dg-error ".y. was not declared in this scope" }
return 0;
Expand Down
26 changes: 26 additions & 0 deletions gcc/testsuite/g++.dg/contracts/new/pr113968.C
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// { dg-do compile }
// { dg-options "-std=c++23 -fcontracts -fcontracts-nonattr" }
struct A {
A(A &);
};
struct S{
void f(A a) pre(a) // { dg-error "could not convert" }
pre(a.b) // { dg-error "has no member" }
{

}
};
void f(A a) pre(a) // { dg-error "could not convert" }
pre(a.b) // { dg-error "has no member" }
{
contract_assert(a); // { dg-error "could not convert" }
contract_assert(a.b); // { dg-error "has no member" }
}

int main()
{
}




26 changes: 26 additions & 0 deletions gcc/testsuite/g++.dg/contracts/pr113968.C
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// { dg-do compile }
// { dg-options "-std=c++2a -fcontracts " }
struct A {
A(A &);
};
struct S{
void f(A a) [[ pre : a]] // { dg-error "could not convert" }
[[ pre : a.b]] // { dg-error "has no member" }
{

}
};
void f(A a) [[ pre : a]] // { dg-error "could not convert" }
[[ pre : a.b]] // { dg-error "has no member" }
{
[[ assert : a ]] ; // { dg-error "could not convert" }
[[ assert : a.b ]]; // { dg-error "has no member" }
}

int main()
{
}




0 comments on commit 5d5df29

Please sign in to comment.