Statische Codeanalyse: Probleme mit ADL in Templates finden


  • Mod

    Hallo zusammen,

    spaßeshalber habe ich mir mal den neuesten GCC (4.8 experimental) installiert. Habe dann festgestellt, dass er standardkonformer geworden ist und nun bei folgendem Konstrukt einen Fehler wirft:
    http://clang.llvm.org/compatibility.html#dep_lookup
    (und auch bei den auf den Link folgenden Konstrukten)

    Nun habe ich eine etwas größere, nicht von mir geschriebene, Bibliothek, die an einigen Stellen (vermutlich eher versehentlich, denn meistens ist es richtig gemacht), diesen Fehler zeigt. Wie habe ich die Fehlerstellen gefunden? Weil mein Code nicht mehr compilierte. Logischerweise finde ich dadurch aber nur Fehler in Funktionen, die ich auch tatsächlich benutze, die Bibliothek hat aber hunderte Funktionen die ich derzeit nicht nutze, aber trotzdem nach dem Fehler durchsuchen möchte. Von Hand wäre das viel zu aufwendig. Hat jemand eine Idee, wie ich das automatisieren könnte?



  • Ein Algorithmus müsste ungefähr so aussehen:
    1. finde alle Deklarationen, in denen eine Funktionsüberladung, die nicht per ADL gefunden werden kann, erstmalig deklariert wird. Ein Überladung kann nicht per ADL gefunden werden, wenn sie nicht in einem Namensraum deklariert wird, der mit einem ihrer Parameter assoziert ist (bzw. im Falle von Templates existiert mindestens eine Spezialisierung dieser Art).
    2. finde Templatedefinitionen, die lexikalisch vor diesen Deklarationen liegen, und sie (potentiell) verwenden. Das könnte ggf. schwierig werden, wenn sie in verschiedenen Dateien liegen, dann müsste man eigentlich jede mögliche include-Reihenfolge betrachten. Operatoren sind auf diese Weise auch nicht einfach zu finden.
    3. Untersuche die Kandidatenliste manuell. Dank using-Deklarationen und Direktiven dürften ein paar Scheinprobleme auftauchen, und dann ist es ja sowieso nicht immer ganz einfach, herauszufinden, welche Überladung denn nun konkret gebraucht werden wird.

    Zumindest der 1. Schritt dürfte vergleichsweise einfach automatisch durchführbar sein.



  • Müssten diese Fehler nicht sowieso per Unittest gefunden werden? Schließlich "verstecken" sie sich ja nur weil das Template nicht instanziiert wurde. Wenn aber ein Unittest läuft, macht er doch genau das...?



  • Könntest du nicht mal mit Clang ausprobieren? ... Ich weiß nicht wie weit der C++ Support ist, aber wenn alles unterstützt wird, sollte die statische Analyse von Clang die Fehler finden, wenn das Pattern bekannt gegeben ist.


  • Mod

    Shade Of Mine schrieb:

    Müssten diese Fehler nicht sowieso per Unittest gefunden werden? Schließlich "verstecken" sie sich ja nur weil das Template nicht instanziiert wurde. Wenn aber ein Unittest läuft, macht er doch genau das...?

    😃 Wenn die Bibliothek Unittests hätte, dann bräuchte ich nicht zu fragen. Die stammt aus dem akademischen Bereich, da bin ich schon froh, dass die in (bis auf diese Sache) ziemlich sauberem C++ geschrieben ist.

    @camper: Würde das nicht darauf hinauslaufen, einen C++-Parser zu schreiben?

    @Zeus: Der kann das? Klingt gut, werde ich mal ausprobieren. Aber wie soll das funktionieren? Man könnte ja Szenarien konstruieren, in denen durch geschickte Wahl des Templateparameters kein Fehler auftritt (dann aber etwas ganz anderes aufgerufen würde als man eigentlich erwartet, deswegen ist es ja ein Fehler). Das Problem tritt ja erst bei Instanzierung mit einem "normalen" Templateparameter auf.



  • Ops Schnellschuß, sorry 😃 Auf der Seite des Analyzer für Clang ist kein Wort geschrieben, dass Template in irgendeine Art in der statischen Analyse berücksichtigt werden können.



  • SeppJ schrieb:

    @camper: Würde das nicht darauf hinauslaufen, einen C++-Parser zu schreiben?

    Im Endeffekt. Allerdings ist mir mittlerweile aufgefallen, dass Schritt 1 so nicht funktioniert. Ob eine Funktion per ADL gefunden werden kann, hängt nicht von deren Parametern, sondern von den tatsächlichen Funktionsargumenten ab, kann also nur beim Aufruf festgestellt werden.
    Ohne Compilermodifikation dürfte diese Fehlerart also nur sehr schwer automatisiert zu fassen sein.

    Mit Compileranpassung könnte man Kandidaten eventuell dadurch zu fassen bekommen, dass man sämtliche in einer ÜE definierten Templates noch einmal am Ende parst und vergleicht, ob sich dadurch die per unqualifiziertem oder qualifiziertem Lookup gefundenen Kandidatenmengen von denen an der tatsächlichen Stelle der Definition unterscheiden. Das ist aber auch nur ein Indeiz, ein Fehler wird es (u.U.) ja erst dann, wenn das Template instantiiert wird und sich durch diese größere Kandidatenmenge die Überladungsauflösung verändert.



  • Vielleicht wäre es ja einfacher, alle Templates zu finden und dann für einige Type zu instantiieren. Die Ausgabe des Programms könnte dann so aussehen:

    template class A<int, int, int>;
    template class B<int, int>;
    ...
    

    Dann muss man nur diese Datei compilieren und die Fehlermeldungen prüfen.


Anmelden zum Antworten