У меня ушло навсегда, чтобы отследить, что в моем коде была ошибка, вызванная /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 или другое), которые могут анализировать мой код и сообщать мне, где я сравниваю указатели функций друг с другом, как в коде выше?
Есть ли какая-либо опция или инструмент компилятора (будь то часть 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);
Или что-то близкое к этому.
Других решений пока нет …