Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions src/lower_il.c
Original file line number Diff line number Diff line change
Expand Up @@ -20305,14 +20305,16 @@ Do IL lowering of the indicated statement and everything under it.
switch (statement->kind) {
case stmk_empty:
/* If the statement includes an [[assume(...)]] attribute, lower
its operand. */
its operand. The operand is not the statement's own expression,
so do not pass the statement (inlining a call would then turn
the statement into a block and drop the attribute). */
for (an_attribute *ap = statement->attributes;
ap != NULL;
ap = ap->next) {
if (ap->kind == ak_assume) {
an_expr_node *expr = expr_node_from_attribute_arg(ap->arguments);
if (expr != NULL) {
lower_full_expr(expr, statement);
lower_full_expr(expr, (a_statement_ptr)NULL);
} /* if */
} /* if */
} /* for */
Expand Down
15 changes: 15 additions & 0 deletions src/pending_changes/gh-393-assume-inlined-call.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
[GH #393]
IL write/read check failure for [[assume]] with an inlinable call

When lowering the argument of an [[assume]] attribute, the empty statement
that carries the attribute was passed to the lowering of the expression as
if the argument were the statement's own expression. If the argument was a
call that could be inlined (for example, a call to a constexpr function),
the inlining turned the statement into a block and the attribute was lost.
In a debug build, the IL write/read check then failed with "not all
expected entries were read". For example:

constexpr bool g(bool b) { return b; }
constexpr int f(bool b) { [[assume(g(b))]]; return 1; }

The argument is now lowered without a statement, so the attribute is kept.
1 change: 1 addition & 0 deletions tests/tests/changes/.GH393.rto/default.1.1.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
fe_only -DTEST_NUMBER=1 --c++23 Test_name.c
26 changes: 26 additions & 0 deletions tests/tests/changes/GH393.sft.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
//type:fp
//options:--c++23
//remark:[GH #393] [[assume]] with an inlinable call in its argument
//
// Lowering inlined a call in an [[assume]] argument by turning the empty
// statement that carries the attribute into a block, which lost the
// attribute. The IL write/read check then failed with "not all expected
// entries were read" for the scoped-expression entry of the attribute
// argument.

int nc();
constexpr bool g(bool b) { return b; }
constexpr bool g1() { return nc() > 0; }
constexpr bool g2(bool b) { if (!b) throw 1; return b; }
inline bool g3(bool b) { return b; }

constexpr int f(bool b) { [[assume(g(b))]]; return 1; }
constexpr int f1() { [[assume(g1())]]; return 1; }
constexpr int f2(bool b) { [[assume(g2(b))]]; return 1; }
int f3(bool b) { [[assume(g3(b))]]; return 1; }
consteval int f4(bool b) { [[assume(g(b))]]; return 1; }
constexpr int f5(bool b) { [[assume(g(b))]]; [[assume(g(b))]]; return 1; }

int use(bool b) {
return f(b) + f1() + f2(b) + f3(b) + f4(true) + f5(b);
}
Loading