mirror of
https://gitlab.freedesktop.org/libinput/libinput.git
synced 2025-12-24 15:50:07 +01:00
util-list: restore list_for_each_safe() to be a single statement
3d3d9b7f69 got rid of the need for a tmp
argument for list_for_each_safe() but switched the loop to be a
multiline statement. This could potentially cause bugs where the loop is
used inside a block without curly braces, e.g.
if (condition)
list_for_each_safe()
func()
The assignment preceding the actual loop would result in the code
reading as:
if (condition)
pos = ....
list_for_each_safe()
The actual list loop would be unconditional.
Fix this by moving the initial assignment into an expression statement.
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
This commit is contained in:
parent
29d311d634
commit
492f6817d3
2 changed files with 38 additions and 2 deletions
|
|
@ -189,8 +189,10 @@ bool list_empty(const struct list *list);
|
|||
* @endcode
|
||||
*/
|
||||
#define list_for_each_safe(pos, head, member) \
|
||||
pos = list_first_entry_by_type(head, __typeof__(*pos), member); \
|
||||
for (__typeof__(pos) _tmp = list_first_entry_by_type(&pos->member, __typeof__(*_tmp), member); \
|
||||
for (__typeof__(pos) _tmp = ({ \
|
||||
pos = list_first_entry_by_type(head, __typeof__(*pos), member); \
|
||||
list_first_entry_by_type(&pos->member, __typeof__(*_tmp), member); \
|
||||
}); \
|
||||
&pos->member != (head); \
|
||||
pos = _tmp, \
|
||||
_tmp = list_first_entry_by_type(&pos->member, __typeof__(*_tmp), member))
|
||||
|
|
|
|||
|
|
@ -1295,6 +1295,39 @@ START_TEST(list_test_append)
|
|||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(list_test_foreach)
|
||||
{
|
||||
struct list_test {
|
||||
int val;
|
||||
struct list node;
|
||||
} tests[] = {
|
||||
{ .val = 1 },
|
||||
{ .val = 2 },
|
||||
{ .val = 3 },
|
||||
{ .val = 4 },
|
||||
};
|
||||
struct list_test *t;
|
||||
struct list head;
|
||||
|
||||
list_init(&head);
|
||||
|
||||
ARRAY_FOR_EACH(tests, t) {
|
||||
list_append(&head, &t->node);
|
||||
}
|
||||
|
||||
/* Make sure both loop macros are a single line statement */
|
||||
if (false)
|
||||
list_for_each(t, &head, node) {
|
||||
ck_abort_msg("We should not get here");
|
||||
}
|
||||
|
||||
if (false)
|
||||
list_for_each_safe(t, &head, node) {
|
||||
ck_abort_msg("We should not get here");
|
||||
}
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(strverscmp_test)
|
||||
{
|
||||
ck_assert_int_eq(libinput_strverscmp("", ""), 0);
|
||||
|
|
@ -1427,6 +1460,7 @@ litest_utils_suite(void)
|
|||
|
||||
tcase_add_test(tc, list_test_insert);
|
||||
tcase_add_test(tc, list_test_append);
|
||||
tcase_add_test(tc, list_test_foreach);
|
||||
tcase_add_test(tc, strverscmp_test);
|
||||
tcase_add_test(tc, streq_test);
|
||||
tcase_add_test(tc, strneq_test);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue