llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
27.92k stars 11.52k forks source link

[CoverageMapping] fail to evaluate "constant folded" conditions at compile time #101241

Open whentojump opened 1 month ago

whentojump commented 1 month ago

Reduced examples:

#include <stdbool.h>

bool x;
bool y;
bool z;

bool *ptr;

int main(int argc, char **argv) {

    //// Expected ////

    if (x && 1)
        return 1;

    if (x && (&y != (void *) 0))
        return 2;

    //// Not expected ////

    // Fail to evaluate "constant folded" at compile time
    if (x && ((ptr = &y) != (void *) 0))
        return 3;

    // Fail to evaluate "constant folded" at compile time, even though the
    // compiler warns about it.
    if (x && (y, 1))
        return 4;

    // Fail to evaluate "constant folded" at compile time, even though the
    // compiler warns about it.
    if (x && (y != 123))
        return 5;

    // Fail to evaluate "constant folded" at compile time, even though the
    // compiler warns about it.
    if (x && (y == y))
        return 6;
}

Compiler explorer link

For decisions in the /// Not expected /// section, the second condition can be evaluated to constant at compile time (in some cases, the compiler is indeed aware of that and produces warnings) but their corresponding branch regions are not 0, 0. As a result, in branch coverage or MC/DC they are not reported as "folded".

On the other hand gcov can detect all cases. (Although it totally disregards them and doesn't have a third state like "folded")

cc @evodius96

evodius96 commented 1 month ago

Thanks for filing this. My notes: CounterCoverageMappingBuilder::ConditionFoldsToBool() relies on Expr::EvaluateAsInt(), which is checked throughout CodeGen for constant folding. However, we probably need to check Expr::EvaluateAsBooleanCondition() additionally (or maybe instead of). Conceptionally it should be easy to extend to support the /// Not expected /// cases.