c++ - hashtags - ¿Alguna forma de generar advertencias para comparaciones de puntero de función?
hashtags en español (1)
Me llevó una eternidad descubrir que había un error en mi código activado por /OPT:ICF
:
Debido a que / OPT: ICF puede hacer que la misma dirección se asigne a diferentes funciones o miembros de datos de solo lectura (const las compiladas compiladas con / Gy), puede romper un programa que depende de direcciones únicas para funciones o miembros de datos de solo lectura .
(Había estado almacenando y comparando punteros de función para la igualdad, que se rompe cuando el vinculador desecha funciones idénticas).
Ahora necesito encontrar cada lugar donde podría haber hecho tal cosa.
El caso de prueba es, por supuesto, trivial:
//MSVC: /Gy /link /OPT:ICF
int test1(void) { return 0; }
int test2(void) { return 0; }
int main(void) { return test1 == test2; }
He intentado -Wall
, -Wextra
, -Weverything
, -pedantic
, etc. pero ninguno de ellos genera advertencias.
¿Hay alguna opción o herramienta del compilador (ya sea parte de Visual C ++, GCC, Clang u otra) que pueda analizar mi código y decirme dónde estoy comparando los punteros de función entre sí, como en el código anterior?
¿Hay alguna opción o herramienta del compilador (ya sea parte de Visual C ++, GCC, Clang u otra) que pueda analizar mi código y decirme dónde estoy comparando los punteros de función entre sí, como en el código anterior?
No estoy seguro de si existe tal opción de compilador.
Sin embargo, existe una herramienta de este tipo. clang-ordenado Puedes escribir tus propios cheques para clang-tidy, en realidad es muy fácil si sigues este blog . Específicamente, el AST ya viene con un montón de comparadores, que deben manejar el caso de uso que desee.
Algo como esto parece funcionar:
binaryOperator(
anyOf(hasOperatorName("=="), hasOperatorName("!=")),
hasLHS(ignoringImpCasts(declRefExpr(hasType(functionType())))),
hasRHS(ignoringImpCasts(declRefExpr(hasType(functionType())))))
Que marca el ejemplo en el OP:
fp.cxx:3:25: note: "root" binds here
int main(void) { return test1 == test2; }
^~~~~~~~~~~~~~
Eso funciona específicamente para el caso OP, pero en realidad debe ser más explícito para que coincida con todos los otros casos probables:
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);
O algo parecido a ese efecto.