Closed horenmar closed 2 years ago
clang-tidy's bugprone-infinite-loop triggers for loops that are easily provable to be finite, in cases like this: [...]
bugprone-infinite-loop checks whether the condition is "known false", and, if not, assumes that it is "potentially true" and thus might be an infinite loop. Furthermore, the current logic bails out if the condition depends on template parameters, i.e. loops whose condition (transitively) depends on a template parameter are never "known false", which explains why your first example triggers the warning while the second example does not.
Obviously, fully solving this problem would require some kind of satisfiability solver (to see whether any choice of dependent variables might make the condition true), but I'm working on a patch that should cover the most common cases, including the examples you have given.
assigned to @fabianwolff
Extended Description
clang-tidy's bugprone-infinite-loop triggers for loops that are easily provable to be finite, in cases like this:
template
int a() { return 1; }
template
void foo() {
const int error = a();
do {} while ( false && error == 0);
}
int main() { foo();
}
The loop is obviously finite (
false && error == 0
is alwaysfalse
, thus the loop will only ever run once), but clang-tidy does not see this and issuesbugprone-infinite-loop
instead (https://godbolt.org/z/vh69oMbsx).Interestingly, relatively small changes to the body of foo can change whether the diagnostic is issued or not, as the code below is (correctly) not diagnosed as infinite:
int a() { return 1; }
template
void foo() {
const int error = a();
do {} while (false && error == 0);
}
int main() { foo();
}
(see https://godbolt.org/z/rzheEfEWh)
Further context
The original reproducer comes from Catch2, where the
REQUIRE
macro expands into a similar loop, specificallydo { // code that tests the expression } while ((void)0, (false) && static_cast<const bool&>( !!(__VA_ARGS__) ) )
the construction is a bit weird (there are underlying reasons), but ultimately the condition always resolves to false. However, when used in combination with
TEMPLATE_TEST_CASE
, which is a macro used for writing type-parametrized tests, it trigers false-positive diagnostic ofbugprone-infinite-loop
.From looking around, this bug was already reported and solved once for the simple case, where the loop is not inside a macro, in llvm/llvm-project#44161 , but that caused a regression, reported in llvm/llvm-project#44239 , and fixed in https://reviews.llvm.org/rG8c4cf23dee1ac3f259c4795b275cc9bb1234aa29 which I suspect causes the error here.