It took me forever to track down that there was a bug in my code being triggered by /OPT:ICF
:
Because /OPT:ICF can cause the same address to be assigned to different functions or read-only data members (const variables compiled by using /Gy), it can break a program that depends on unique addresses for functions or read-only data members.
(I had been storing and comparing function pointers for equality, which breaks when the linker throws away identical functions.)
Now I need to find every place where I might have done such a thing.
The test case is of course trivial:
//MSVC: /Gy /link /OPT:ICF int test1(void) { return 0; } int test2(void) { return 0; } int main(void) { return test1 == test2; }
I've tried -Wall
, -Wextra
, -Weverything
, -pedantic
, etc. but none of them generate warnings.
Is there any compiler option or tool (whether part of Visual C++, GCC, Clang, or other) that can analyze my code and tell me where I'm comparing function pointers with each other, like in the code above?
Two function pointers can be compared with the == and != operators, just like any other kind of pointers. We can also compare a function pointer to the NULL pointer using the == and != operators.
Pointers to member functions in C++ This is how C++ uses function pointers when dealing with member functions of classes or structs. These are invoked using an object pointer or a this call. They are type safe in that you can only call members of that class (or derivatives) using a pointer of that type.
When a pointer is incremented, it actually increments by the number equal to the size of the data type for which it is a pointer. For Example: If an integer pointer that stores address 1000 is incremented, then it will increment by 2(size of an int) and the new address it will points to 1002.
A delegate is a type-safe function pointer that can reference a method that has the same signature as that of the delegate. You can take advantage of delegates in C# to implement events and call-back methods. A multicast delegate is one that can point to one or more methods that have identical signatures.
Is there any compiler option or tool (whether part of Visual C++, GCC, Clang, or other) that can analyze my code and tell me where I'm comparing function pointers with each other, like in the code above?
I'm not sure if there exists such a compiler option.
However, there is such a tool. clang-tidy. You can write your own checks for clang-tidy, it's actually remarkably easy if you follow this blog. Specifically, the AST comes with a bunch of matchers already, which should handle the use-case you want.
Something like this seems to work:
binaryOperator( anyOf(hasOperatorName("=="), hasOperatorName("!=")), hasLHS(ignoringImpCasts(declRefExpr(hasType(functionType())))), hasRHS(ignoringImpCasts(declRefExpr(hasType(functionType())))))
Which flags the example in the OP:
fp.cxx:3:25: note: "root" binds here int main(void) { return test1 == test2; } ^~~~~~~~~~~~~~
That works specifically for the OP case, but you actually have to be more explicit to match all the other likely cases:
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);
Or something close to that effect.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With