Blog 4 Min. Lesezeit

Was kann Clang über Ihre Visual-C++-Projekte verraten?

Artikel teilen
What Can Clang Tell You About Your Visual C++ Projects?

Jeder Compiler kann nach einem Build zahlreiche Warnungen ausgeben. Diese Warnungen verhindern die Kompilierung Ihres Codes nicht, sofern Sie sie nicht ausdrücklich als Fehler behandeln. Nehmen Sie sich die Zeit, diese Warnungen zu prüfen, anstatt sie zu ignorieren. Compilerwarnungen sind häufig Hinweise auf potenzielle Fehler, die andernfalls möglicherweise erst zur Laufzeit auftreten würden.

Clang ist ein C/C++/Objective-C-Compiler mit vielen nützlichen Funktionen. Zu den wichtigsten Funktionen für Anwender gehören:

  • Schnelle Kompilierung und geringer Speicherverbrauch.
  • Aussagekräftige Diagnosen.
  • Kompatibilität mit GCC.

In diesem Beitrag konzentrieren wir uns auf die aussagekräftigen Diagnosen von Clang und zeigen, wie Sie diese für Visual-C++-Projekte erhalten.

Das Clang-Team hat sich zum Ziel gesetzt, Fehlermeldungen so klar und informativ wie möglich zu gestalten. Für einen Kommandozeilen-Compiler sollen sie möglichst benutzerfreundlich sein. Dazu zeigt Clang präzise auf, was im Code nicht stimmt. Eine Diagnose-Engine verarbeitet die Fehlerinformationen und formuliert daraus eine verständliche Meldung.

Um die Vorteile der Clang-Diagnosen zu verdeutlichen, kompilieren wir eine minimale C++-Quelldatei sowohl mit Visual C++ als auch mit Clang und vergleichen die ausgegebenen Warnungen. Bei beiden Compilern werden sämtliche Warnungen aktiviert.

clang1

Der Microsoft-C++-Compiler meldet folgende Warnung:

  • warning C4100: ‘n’: unreferenced formal parameter

Clang meldet drei Warnungen:

  • no previous prototype for function ‘Print’
  •  use of old-style cast
  • unused parameter ‘n’

Interessant an Clang ist, dass der Compiler auch Diagnosen zu bewährten Programmierpraktiken ausgibt. Die Warnung „no previous prototype for function Print“ erscheint beispielsweise, weil Print nicht als statische Funktion deklariert ist und daher aus einer anderen Quelldatei verwendet werden könnte. In diesem Fall empfiehlt es sich, die Deklaration in einer Headerdatei abzulegen.

Um ein konkreteres Bild von den Clang-Diagnosen zu erhalten, kompilieren wir ein Open-Source-C++-Projekt sowohl mit Clang als auch mit dem Microsoft-Compiler und vergleichen die Arten der gemeldeten Warnungen.

Als Beispiel verwenden wir das Projekt „7-Zip“ und kompilieren ausschließlich das Modul Gui.vcproj. Dabei betrachten wir nur Warnungen, die sich auf den Quellcode des Projekts beziehen, nicht auf externe Include-Dateien.

Der Microsoft-Compiler meldet unter anderem folgende Arten von Warnungen:

  • Bytes padding added after data member.
  • Conversion issues.
  • Function not inlined.
  • Class has virtual functions, but destructor is not virtual.
  • Catch(…) semantics changed since Visual C++ 7.1; structured exceptions (SEH) are no longer caught.
  • Cast issues.
  • Enumerator ‘kInfo’ in switch of enum ‘NCommandType::EEnum’ is not explicitly handled by a case label.
  • ‘GetVersionExA’: was declared deprecated.
Der Clang-Compiler meldet unter anderem folgende Arten von Warnungen:
  • Use of old-style cast
  • Missing field ‘MinLen’ initializer
  • Macro is not used
  • Declaration requires a global constructor
  • Declaration requires an exit-time destructor
  • Conversion issues
  • Cast issues
  • enumeration values ‘kWithoutPrompt’, ‘kAutoRename’, and ‘kAutoRenameExisting’ not handled in switch
  • Operand of ?: changes signedness: ‘const int’ to ‘unsigned int’
  • Declaration shadows a local variable
  • ISO C++11 does not allow conversion from string literal to ‘LPSTR’ (aka ‘char *’)
  • No previous prototype for function
  • Comparison issues
  • ‘GetVersionExA’: was declared deprecated
  • dynamic exception specifications are deprecated
  • ‘&&’ within ‘||’
  • ‘CBenchRandomGenerator’ has no out-of-line virtual method definitions; its vtable will be emitted in every translation unit
  • Delete called on ‘CBenchmarkInStream’ that has virtual functions but non-virtual destructor
  • ‘CBenchmarkInStream’ has virtual functions but non-virtual destructor
  • Equality comparison result unused
  • Explicitly assigning value of variable of type ‘INT_PTR’ (aka ‘int’) to itself
  • Add explicit braces to avoid dangling else

Wie wir sehen, liefert Clang mehr nützliche Warnungen als der Microsoft-Compiler. Einige davon werden normalerweise nur von Werkzeugen zur statischen Analyse gemeldet. Es lohnt sich, diese Warnungen ernst zu nehmen, denn sie können zahlreiche Fehler aufdecken.

Wie erhalten Sie Clang-Diagnosen für Ihre Visual-C++-Projekte?

Clang-Diagnosen helfen Entwicklern, die Qualität ihres C/C++-Quellcodes zu verbessern. Daher ist es sinnvoll, auch bei Visual-C++-Projekten darauf zugreifen zu können.

Die erste Möglichkeit besteht darin, Ihre Projekte mit Clang zu kompilieren. Dieser MSDN-Beitrag zeigt, wie Sie Clang als Compiler in Visual Studio verwenden.

Die zweite Möglichkeit besteht darin, Ihre Visual-Studio-Projekte mit CppDepend, das Clang als Front-End-Parser verwendet und sämtliche Clang-Diagnosen ausgibt. CppDepend ist für die Open-Source-Community kostenlos.

Die folgende Abfrage liefert alle Clang-Diagnosen:

clang6

Das Gui-Projekt der 7-Zip-Anwendung umfasst nur rund 10.000 Codezeilen und weist dennoch 1.186 Diagnosen auf. Bei mittleren und großen Projekten können es Tausende sein. In diesem Fall ist es sinnvoll, die Ergebnisse zu filtern und nur bestimmte Warnungstypen abzurufen.

Beispielsweise können wir die vorherige Abfrage so ändern, dass nur Warnungen zu veralteten Verwendungen ausgegeben werden.

clang8

Fazit:

Warnungen sind häufig Hinweise auf potenzielle Fehler und sollten daher nicht ignoriert werden. Clang liefert zahlreiche nützliche Diagnosen, darunter auch Hinweise auf bewährte Programmierpraktiken. Wer diese Warnungen konsequent behebt, kann die Qualität des Quellcodes eines Projekts deutlich verbessern.

Artikel teilen