29 votes

Est-il possible de générer des avertissements pour les comparaisons de pointeurs de fonction?

Il m'a fallu une éternité pour traquer qu'il y avait un bug dans mon code qui a été déclenché par /OPT:ICF:

Parce que /OPT:ICF peut causer la même adresse pour être affectés à différentes fonctions ou en lecture seule aux données membres (const variables compilé en utilisant /Gy), il peut se casser un programme qui dépend d'adresses uniques pour des fonctions ou des données en lecture seule les membres.

(J'avais le stockage et la comparaison de pointeurs de fonction pour l'égalité, qui se brise lorsque l'éditeur de liens jette fonctions identiques.)

Maintenant, j'ai besoin de trouver tous les endroits où j'ai pu faire une telle chose.

Le cas de test est bien sûr trivial:

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

J'ai essayé d' -Wall, -Wextra, -Weverything, -pedantic, etc. mais aucun d'eux de générer des avertissements.

Est-il tout option du compilateur ou de l'outil (si une partie de Visual C++, GCC, Clang, ou autres) qui peuvent analyser mon code et me dire où je suis la comparaison de pointeurs de fonction les uns avec les autres, comme dans le code ci-dessus?

8voto

Barry Points 45207

Est-il une option du compilateur ou de l'outil (si une partie de Visual C++, GCC, Clang, ou autres) qui peuvent analyser mon code et me dire où je suis la comparaison de pointeurs de fonction les uns avec les autres, comme dans le code ci-dessus?

Je ne sais pas si il existe une option de compilation.

Cependant, il ya un tel outil. clang-propre. Vous pouvez écrire vos propres contrôles pour clang-propre, c'est en fait très facile si vous suivez ce blog. Plus précisément, l'AST est livré avec un tas de rapprochement déjà, qui doit gérer les cas d'utilisation que vous souhaitez.

Quelque chose comme cela semble fonctionner:

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

Qui signale l'exemple de l'OP:

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

Qui travaille spécifiquement pour l'OP cas, mais en fait, vous avez à être plus explicite pour correspondre à tous les autres cas:

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);

Ou quelque chose de proche à cet effet.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X