Охват LLVM перепутан с if-constexpr - PullRequest
0 голосов
/ 28 августа 2018

Я столкнулся со странной проблемой с покрытием LLVM при использовании константных выражений в if-statement:

template<typename T>
int foo(const T &val)
{
    int idx = 0;

    if constexpr(std::is_trivially_copyable<T>::value && sizeof(T) <= sizeof(int)
    {
        memcpy(&idx, &v, sizeof(T));
    }
    else
    {
        //store val and assign its index to idx
    }

    return idx;
}

Выполненные экземпляры:

int idx1 = foo<int>(10);
int idx2 = foo<long long>(10);
int idx3 = foo<std::string>(std::string("Hello"));
int idx4 = foo<std::vector<int>>(std::vector<int>{1,2,3,4,5});

Ни в одном из них sizeof(T) <= sizeof(int) никогда не отображается как выполненный. И все же в первом случае (int) тело первого if действительно выполняется так, как должно. Ни в каком другом случае оно не отображается как выполненное.

Соответствующая часть командной строки компиляции:

/usr/bin/clang++ -g -O0 -Wall -Wextra -fprofile-instr-generate -fcoverage-mapping -target x86_64-pc-linux-gnu -pipe -fexceptions -fvisibility=default -fPIC -DQT_CORE_LIB -DQT_TESTLIB_LIB -I(...) -std=c++17 -o test.o -c test.cpp

Соответствующая часть командной строки компоновщика:

/usr/bin/clang++ -Wl,-m,elf_x86_64,-rpath,/home/michael/Qt/5.11.2/gcc_64/lib -L/home/michael/Qt/5.11.2/gcc_64/lib -fprofile-instr-generate -fcoverage-mapping -target x86_64-pc-linux-gnu -o testd test.o -lpthread -fuse-ld=lld

Когда условие извлекается в его собственную функцию, экземпляры int и long long правильно отображаются в покрытии как выполняющие часть sizeof(T) <= sizeof(int). Что может быть причиной такого поведения и как его решить? Это ошибка в Clang / LLVM cov?

Есть идеи?

EDIT: Кажется, это известная ошибка в LLVM (пока не ясно, LLVM-cov или Clang):

https://bugs.llvm.org/show_bug.cgi?id=36086

https://bugs.chromium.org/p/chromium/issues/detail?id=845575

1 Ответ

0 голосов
/ 28 августа 2018

Прежде всего, sizeof(T) <= sizeof(int) должно выполняться во время компиляции в вашем коде, так что скорее всего, компиляция не профилируется для покрытия.

Далее, из этих трех типов только long long выглядит trivially_copyable, но его размер (весьма вероятно) больше, чем int, поэтому предложение then не выполняется для них и даже не компилируется. Поскольку все происходит внутри шаблонной функции, неисполненная ветвь не компилируется.

...