Ceci est une ancienne révision du document !
Table des matières
clang-tidy détecte les parties du code qui sont soit bancals, soit pourrait être écrite d'une meilleure façon.
Ne pas utiliser :
readability-static-accessed-through-instancedans le cas d'un projetQt. Dans la déclaration des classes, les champspublic : … public slot :seront considérés comme des doublons carslotest enlevé lors du preprocessing.
CMake
S'intègre parfaitement avec CMake.
Il faut commencer par activer l'option set(CMAKE_EXPORT_COMPILE_COMMANDS ON).
Puis lancer la génération des Makefile avec CC="clang" CXX="clang++" cmake -S . -B build pour générer également le fichier compile_commands.json. L'utilisation du compilateur clang n'est pas obligatoire. Elle est simplement là pour vérifier que le code compile bien avec clang.
L'analyse se lance avec run-clang-tidy.
Options
- Configuration des règles
Le fichier de config peut se générer via clang-tidy --dump-config > .clang-tidy. Il est conseillé de générer ce fichier à chaque changement de version de clang, certaines options pouvant être supprimées ou renommées.
Exemple du début du fichier .clang-tidy:
- .clang-tidy
--- Checks: '*,-llvm-header-guard,-modernize-use-trailing-return-type,-cppcoreguidelines-avoid-magic-numbers,-readability-magic-numbers,-fuchsia-default-arguments-calls' WarningsAsErrors: '*' HeaderFilterRegex: '' ...
Clang-Tidy, part 1: Modernize your source code using C++11/C++14 Archive du 16/03/2017 le 13/02/2020
- Analyse uniquement certains dossiers
Il est aussi possible de filtrer certains dossiers :
run-clang-tidy-12 '^((?!/path1/|/path2/).)*$'
- Spécifier la localisation de clang-tidy
Peut être utile si on souhaite utiliser clang-tidy pour Android qui est différent de celui du système mais run-clang-tidy n'est pas fourni dans le SDK Android.
/usr/lib/llvm-14/bin/run-clang-tidy -clang-tidy-binary .../Android/Sdk/ndk/25.1.8937393/toolchains/llvm/prebuilt/linux-x86_64/bin/clang-tidy
- Exclure certains fichiers
Il faut modifier le fichier compile_commands.json avec une commande perl qui autorise les regex multilignes.
perl -0777 -i.original -pe 's/,\n\{\n.*\n.*_RCS_FILES\.cpp",\n.*_RCS_FILES\.cpp"\n\}//g' compile_commands.json perl -0777 -i.original -pe 's/\{\n.*\n.*_RCS_FILES\.cpp",\n.*_RCS_FILES\.cpp"\n\},\n//g' compile_commands.json
Gestion les erreurs
- Ignorer la vérification sur des lignes de code spécifiques
badcode; // NOLINT // NOLINTNEXTLINE badcode; badcode; // NOLINT(cert-err-58-cpp) // NOLINTBEGIN(google*) Foo(bool param); // NOLINTEND(google*)
Détail des règles
readability-identifier-naming
Priorité de la convention de nommage:
Voir directement le code source avec les méthodes findStyleKind, findStyleKindForField et findStyleKindForVar.
Ci-dessous, defined(Xxxx) signifie que XxxxCase, XxxxPrefix, XxxxSuffix, XxxxIgnoredRegex ou XxxxHungarianPrefix est dans les règles.
si (variable Objective-C && defined(ObjcIvar))
=> ObjcIvar
si (typedef && defined(Typedef))
=> Typedef
si (using && defined(TypeAlias))
=> TypeAlias
si (namespace)
si (namespace est inline) && defined(InlineNamespace)
=>InlineNamespace
si defined(Namespace)
=>Namespace
si (enum && defined(Enum))
=> Enum
si (valeur d'un enum)
si (enum class && defined(ScopedEnumConstant))
=> ScopedEnumConstant
si (defined(EnumConstant))
=> EnumConstant
si (defined(Constant))
=> Constant
=> Ignore
si (union ou struct ou class)
si (abstract (au moins une méthode virtuelle pure) && defined(AbstractClass))
=> AbstractClass
si (struct && defined(Struct))
=> Struct
si (struct && defined(Class))
=> Class
si (class && defined(Class))
=> Class
si (class && defined(Struct))
=> Struct
si (union && defined(Union))
=> Union
si (enum && defined(Enum))
=> Enum
=> Ignore
si (membre d'une classe)
si (option CheckAnonFieldInParent && struct/union parent est anonyme)
Appliquer les règles ci-dessous en considérant le private/protected/public du parent.
si (const)
si (defined(ConstantMember))
=> ConstantMember
si (defined(Constant))
=> Constant
si (private && defined(PrivateMember))
=> PrivateMember
si (protected && defined(ProtectedMember))
=> ProtectedMember
si (public && defined(PublicMember))
=> PublicMember
si (defined(Member))
=> Member
=> Ignore
si (paramètre d'une fonction)
si (constexpr && defined(ConstexprVariable)) // C'est possible ?
=> ConstexprVariable
si (const)
si (pointer && defined(ConstantPointerParameter))
=> ConstantPointerParameter
si (defined(ConstantParameter))
=> ConstantParameter
si (defined(Constant))
=> Constant
si (variadic && defined(ParameterPack))
=> ParameterPack
si (pointer && defined(PointerParameter))
=> PointerParameter
si (defined(Parameter))
=> Parameter
=> Ignore
si (variable)
si (constexpr && defined(ConstexprVariable))
=> ConstexprVariable
si (const)
si (static && defined(ClassConstant))
=> ClassConstant
si (global && pointer && defined(GlobalConstantPointer))
=> GlobalConstantPointer
si (global && defined(GlobalConstant))
=> GlobalConstant
si (local && static && defined(StaticConstant))
=> StaticConstant
si (local && pointer && defined(LocalConstantPointer))
=> LocalConstantPointer
si (local && defined(LocalConstant))
=> LocalConstant
si (defined(Constant))
=> Constant
si (static && defined(ClassMember))
=> ClassMember
si (global && pointer && defined(GlobalPointer))
=> GlobalPointer
si (global && defined(GlobalVariable))
=> GlobalVariable
si (local && static && defined(StaticVariable))
=> StaticVariable
si (local && pointer && defined(LocalPointer))
=> LocalPointer
si (local && defined(LocalVariable))
=> LocalVariable
si (defined(Variable))
=> Variable
=> Ignore
si (methode)
si (override)
=> Ignore
si (constexpr && defined(ConstexprMethod))
=> ConstexprMethod
si (constexpr && defined(ConstexprFunction))
=> ConstexprFunction
si (static && defined(ClassMethod))
=> ClassMethod
si (virtual && defined(VirtualMethod))
=> VirtualMethod
si (private && defined(PrivateMethod))
=> PrivateMethod
si (protected && defined(ProtectedMethod))
=> ProtectedMethod
si (public && defined(PublicMethod))
=> PublicMethod
si (defined(Method))
=> Method
si (defined(Function))
=> Function
=> Ignore
si (fonction)
si (constexpr && defined(ConstexprFunction))
=> ConstexprFunction
si (global && defined(GlobalFunction))
=> GlobalFunction
si (defined(Function))
=> Function
si (typename in template)
si (defined(TypeTemplateParameter))
=> TypeTemplateParameter
si (defined(TemplateParameter))
=> TemplateParameter
=> Ignore
si (value in template)
si (defined(ValueTemplateParameter))
=> ValueTemplateParameter
si (defined(TemplateParameter))
=> TemplateParameter
=> Ignore
si (template <typename> class / typename)
si (defined(TemplateTemplateParameter))
=> TemplateTemplateParameter
si (defined(TemplateParameter))
=> TemplateParameter
=> Ignore
si (concept && defined(Concept))
=> Concept
=> Ignore
Extensions
Writing a basic clang static analysis check Archive du 02/05/2015 le 30/06/2021
Et une version à jour du système de compilation : Tutorial for building tools using LibTooling and LibASTMatchers, Archive du clang 17.0.0 master le 23/05/2023
Getting Involved Archive du clang 17.0.0 master le 24/05/2023
Cache
kokulshan/clang-tidy-cache
- Installation
Il faut avoir installé go.
make
- Exécution
CLANG_TIDY_CACHE_BINARY=/usr/bin/clang-tidy-17 CLANG_TIDY_CACHE_DIR=~/.cache/clang-tidy-cache run-clang-tidy-17 -clang-tidy-binary /usr/local/bin/clang-tidy-cache
matus-chochlik/ctcache
- Installation
Il suffit de copier les scripts python clang-tidy et clang-tidy-cache dans /usr/local/bin.
- Execution
CTCACHE_CLANG_TIDY=/usr/bin/clang-tidy CTCACHE_DIR=~/.cache/clang-tidy-cache run-clang-tidy -clang-tidy-binary /usr/local/bin/clang-tidy
