Любой способ генерировать предупреждения для сравнения функций и указателей?

Мне потребовалось время, чтобы отследить, что в моем коде возникла ошибка: /OPT:ICF:

Поскольку /OPT: ICF может назначить один и тот же адрес различным функциям или членам данных только для чтения (константные переменные, скомпилированные с использованием /Gy), он может разорвать программу, которая зависит от уникальных адресов для функций или членов данных только для чтения,

(Я хранили и сравнивал указатели на функции для равенства, что ломается, когда компоновщик выбрасывает идентичные функции.)

Теперь мне нужно найти все места, где я мог бы это сделать.

Тестовый случай, конечно, тривиальный:

//MSVC: /Gy /link /OPT:ICF
int test1(void) { return 0; }
int test2(void) { return 0; }
int main(void) { return test1 == test2; }

Я пробовал -Wall, -Wextra, -Weverything, -pedantic и т.д., Но ни один из них не генерирует предупреждения.

Есть ли какой-либо параметр или инструмент компилятора (будь то часть Visual C++, GCC, Clang или другое), которые могут анализировать мой код и сообщать мне, где я сравниваю указатели на функции друг с другом, например, в коде выше?

Ответ 1

Есть ли какой-либо параметр или инструмент компилятора (будь то часть Visual C++, GCC, Clang или другое), которые могут анализировать мой код и сообщать мне, где я сравниваю указатели на функции друг с другом, например, в коде выше?

Я не уверен, существует ли такая опция компилятора.

Однако есть такой инструмент. лязг-аккуратно. Вы можете написать свои собственные чеки для clang-tidy, это действительно замечательно легко, если вы следуете этому блогу. В частности, AST поставляется с кучей совпадений, которые должны обрабатывать нужное место.

Кажется, что-то вроде этого работает:

binaryOperator(
    anyOf(hasOperatorName("=="), hasOperatorName("!=")),
    hasLHS(ignoringImpCasts(declRefExpr(hasType(functionType())))),
    hasRHS(ignoringImpCasts(declRefExpr(hasType(functionType())))))

Какие флаги являются примером в OP:

fp.cxx:3:25: note: "root" binds here
int main(void) { return test1 == test2; }
                        ^~~~~~~~~~~~~~

Это работает специально для случая OP, но вы действительно должны быть более явным, чтобы соответствовать всем другим вероятным случаям:

const auto AnyFunc = ignoringImpCasts(declRefExpr(hasType(anyOf(
    functionType(),
    pointsTo(functionType()),
    references(functionType())))));

Finder->AddMatcher(binaryOperator(
    anyOf(hasOperatorName("=="), hasOperatorName("!=")),
    hasLHS(AnyFunc),
    hasRHS(AnyFunc)).bind("op"), this);

Или что-то близко к этому.