Outils pour utilisateurs

Outils du site


prog:clang-tidy

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-instance dans le cas d'un projet Qt. Dans la déclaration des classes, les champs public : … public slot : seront considérés comme des doublons car slot est 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.

Algo Exemple
variable objective-C:
  si SK_ObjcIvar:
    SK_ObjcIvar
  sinon
    fin
 
typedef:
  si SK_Typedef:
    SK_Typedef
  sinon
    fin
typedef int INTeGER;
using:
  si SK_TypeAlias:
    SK_TypeAlias
  sinon
    fin
using DOUbLE = double;
namespace:
  si inline namespace && SK_InlineNamespace:
    SK_InlineNamespace
  si SK_Namespace
    SK_Namespace
  fin
inline namespace NAMEsPACE {}
 
namespace nAMEPACE {}
enum:
  si enum && SK_Enum:
    SK_Enum
  fin

field in enum:
  si enum class && SK_ScopedEnumConstant:
    SK_ScopedEnumConstant
  si SK_EnumConstant:
    SK_EnumConstant
  si SK_Constant:
    SK_Constant
  fin
enum eNUM { EnuM_CONST };
 
enum class eNUM { ENUM_Const };
union ou struct ou class:
  si abstract (une méthode virtuelle pure) && SK_AbstractClass:
    SK_AbstractClass
  si struct && SK_Struct:
    SK_Struct
  si struct && SK_Class:
    SK_Class
  si class && SK_Class:
    SK_Class
  si class && SK_Struct:
    SK_Struct
  si union && SK_Union:
    SK_Union
  si enum && SK_Enum:
    SK_Enum
  fin
class ABStract {
  virtual fOo() = 0;
};
 
struct STRuct {};
 
class ClAsS {};
 
union UnIon {};
 
enum class eNUM {};
membre d'une classe:
  si CheckAnonFieldInParent && struct/union parent est anonyme:
    Appliquer les règles ci-dessous en
      considérant le private/protected/public du parent.
  si const:
    si SK_ConstantMember:
      SK_ConstantMember
    si SK_Constant:
      SK_Constant
  si private && SK_PrivateMember:
    SK_PrivateMember
  si protected && SK_ProtectedMember:
    SK_ProtectedMember
  si public && SK_PublicMember:
    SK_PublicMember
  si SK_Member:
    SK_Member
  fin
class {
  const int InT;
 
private:
  short ShorT;
 
protected:
  double DoublE;
 
public:
  float FloaT;
}
paramètre:
  // Possible en C++ ?!?
  si constexpr && SK_ConstexprVariable:
    SK_ConstexprVariable
  si const:
    si pointeur && SK_ConstantPointerParameter:
      SK_ConstantPointerParameter
    si SK_ConstantParameter:
      SK_ConstantParameter
    si SK_Constant:
      SK_Constant
  si variadic && SK_ParameterPack:
    SK_ParameterPack
  si pointeur && SK_PointerParameter:
    SK_PointerParameter
  si SK_Parameter:
    SK_Parameter
  fin
template <class... Types>
void fOo(const int *IiI, const short &ShorT,
         int *JjJ, short SsS, Types... arGs);
variable:
  si constexpr && SK_ConstexprVariable:
    SK_ConstexprVariable
  si const:
    si static && membre && SK_ClassConstant:
      SK_ClassConstant
    si global && pointeur && SK_GlobalConstantPointer:
      SK_GlobalConstantPointer
    si global && SK_GlobalConstant:
      SK_GlobalConstant
    si local && static && SK_StaticConstant:
      SK_StaticConstant
    si local && pointeur && SK_LocalConstantPointer:
      SK_LocalConstantPointer
    si local && SK_LocalConstant:
      SK_LocalConstant
    // Plus restrictif que la condition précédente ?!?
    si local && dans le bloc principal
      de la fonction/méthode && SK_LocalConstant:
        SK_LocalConstant
    si SK_Constant:
      SK_Constant
  fin
  si static && membre && SK_ClassMember:
    SK_ClassMember
  si global && pointeur && SK_GlobalPointer:
    SK_GlobalPointer
  si global && SK_GlobalVariable:
    SK_GlobalVariable
  si local && static && SK_StaticVariable:
    SK_StaticVariable
  si local && pointeur && SK_LocalPointer:
    SK_LocalPointer
  si local && SK_LocalVariable:
    SK_LocalVariable
  // Plus restrictif que la condition précédente ?!?
  si local && dans le bloc principal
    de la fonction/méthode && SK_LocalVariable:
      SK_LocalVariable
  si SK_Variable:
    SK_Variable
  fin
constexpr int eE = 150;
 
class Cc {
  static const int Ee = 150;
};
 
const int *Jj = nullptr;
const int jJ = 0;
 
void fOo() {
  static const int zZZz = 150;
  const int *ZzzZ = nullptr;
  {
    const int ZZzz = 150;
  }
  const int ZZzZ = 150;
};
 
class Cc2 {
  static int Ee2 = 150;
};
 
int *Jj2 = nullptr;
int jJ2 = 0;
 
void fOo2() {
  static int zZZz2 = 150;
  int *ZzzZ2 = nullptr;
  {
    int ZZzz2 = 150;
  }
  int ZZzZ2 = 150;
};
méthode:
  si override:
    ignore
  si constexpr && SK_ConstexprMethod:
    SK_ConstexprMethod
  si constexpr && SK_ConstexprFunction:
    SK_ConstexprFunction
  si static && SK_ClassMethod:
    SK_ClassMethod
  si virtual && SK_VirtualMethod:
    SK_VirtualMethod
  si private && SK_PrivateMethod:
    SK_PrivateMethod
  si protected && SK_ProtectedMethod:
    SK_ProtectedMethod
  si public && SK_PublicMethod:
    SK_PublicMethod
  si SK_Method:
    SK_Method
  si SK_Function:
    SK_Function
  ignore
class A{
    public:
    virtual void fOo()= 0;
};
 
class B:public A{
    public:
    void fOo() override;
 
    constexpr int fOo2();
    static void fOo3();
 
    virtual void fOo4();
 
    private:
     void fOo5();
    protected:
     void fOo6();
    public:
     void fOo7();
};
fonction:
  si constexpr && SK_ConstexprFunction:
    SK_ConstexprFunction
  // C'est quoi une fonction non globale ?
  si global && SK_GlobalFunction:
    SK_GlobalFunction
  si SK_Function:
    SK_Function
  ignore
constexpr void b1r();
void bAr();
typename dans template:
  si SK_TypeTemplateParameter:
    SK_TypeTemplateParameter
  si SK_TemplateParameter:
    SK_TemplateParameter
  ignore

value in template:
  si SK_ValueTemplateParameter:
    SK_ValueTemplateParameter
  si SK_TemplateParameter:
    SK_TemplateParameter
  ignore

template <typename> class / typename:
  si SK_TemplateTemplateParameter:
    SK_TemplateTemplateParameter
  si SK_TemplateParameter:
    SK_TemplateParameter
  ignore
template<typename TypeName, int VaLuE,
  template<typename> typename TypeTypeName>
void FoBa();
concept && SK_Concept:
  SK_Concept
template<class T, class U>
concept ConCepT = std::is_base_of<U, T>::value;
define && SK_MacroDefinition:
  SK_MacroDefinition
#define MaCrO

Extensions

Cache

kokulshan/clang-tidy-cache

Site web

  • 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

Site web

  • 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
prog/clang-tidy.txt · Dernière modification : 2024/12/23 09:44 de root