29

我花了很长时间才发现我的代码中有一个错误被触发/OPT:ICF

因为/OPT:ICF 会导致将相同的地址分配给不同的函数或只读数据成员(使用 /Gy 编译的 const 变量),它可能会破坏依赖于函数或只读数据成员的唯一地址的程序.

(我一直在存储和比较函数指针是否相等,当链接器丢弃相同的函数时它会中断。)

现在我需要找到我可能做过这种事情的每个地方。

测试用例当然是微不足道的:

//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 或其他的一部分)可以分析我的代码并告诉我在哪里比较函数指针,就像上面的代码一样?

4

1 回答 1

8

是否有任何编译器选项或工具(无论是 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);

或者接近那种效果的东西。

于 2018-01-30T17:06:18.287 回答