clang-tidy: identify "C++-code-specific-checks" and "C-Code-specific-checks"

Greetings!

We are using clang-tidy with single ‘config-file’ listing enabled tidy-checks to run for both “C+±code” and “C-code”.

We are looking for your inputs:

Hello,

Please see my comments inlined.

[1] https://clang-analyzer.llvm.org/available_checks.html

Greetings!

We are using clang-tidy with single ‘config-file’ listing enabled tidy-checks to run for both “C++-code” and “C-code”.

We are looking for your inputs:
From list of supported clang-tidy checks, how to identify "C++-code-specific-checks" and which are "C-Code-specific-checks"? Can this be checked programmatically?

    What are you trying to achieve? clang-tidy addresses more C++ checkers, I don’t recall seeing C specific checkers and no, you cannot determine this programatically since it’s a matter of matching at the AST level.

Are “clang-analyzer-“ checks only applied to C++-code?

         No, there are a wide variaty of checkers that apply to C and C++ [1]

What happens internally if C++-code-check ran on C-code? Will it skip parsing C-code?

    Nothing really, since the clang-tidy checkers are implemented mostly as matcher at the AST level and since specific nodes that are matched for a checkers are not present in the AST the checker will not get triggered.

From list of supported clang-tidy checks, how to identify “C+±code-specific-checks” and which are “C-Code-specific-checks”? Can this be checked programmatically?

What are you trying to achieve? clang-tidy addresses more C++ checkers, I don’t recall seeing C specific checkers and no, you cannot determine this programatically since it’s a matter of matching at the AST level.

We are seeing tidy taking lot of time for .c files and some .cc files!

On running each check we observed two things:

  1. clang-analyzers are taking contributing lot and

  2. “cert-dcl16-c” check is same as “readability-uppercase-literal-suffix” and “hicpp-uppercase-literal-suffix”. We all three enabled and these three also taking time!

So my understanding is – if we have these three checks “cert-dcl16-c”, “readability-uppercase-literal-suffix” and “hicpp-uppercase-literal-suffix” enabled it will parse AST thrice, correct? Shouldn’t it run once?

We would like to run specific tidy-checks for only C-code and specific tidy check for C+±code.

I think tidy performance can be improved if tidy can check file type (either C++ or C), decide whether specific check relevant to C+±code OR C-code and then only parse AST, isn’t it?

For example, tidy should not spend time in parsing C-code if check is about Virtual-Calls/Function etc. e.g.

Just like https://clang.llvm.org/docs/analyzer/checkers.html#core-nulldereference which specifies check is for C++ or C or ObjC… something similar should be there for clang-tidy.

Are “clang-analyzer-“ checks only applied to C+±code?

No, there are a wide variaty of checkers that apply to C and C++ [1]

What happens internally if C+±code-check ran on C-code? Will it skip parsing C-code?

Nothing really, since the clang-tidy checkers are implemented mostly as matcher at the AST level and since specific nodes that are matched for a checkers are not present in the AST the checker will not get triggered.
As mentioned above, (a) can tidy be improved to parse AST only if check relevant to C++ or C code? OR just like https://clang.llvm.org/docs/analyzer/checkers.html#core-nulldereferencecan can tidy highlight which checks are for C++ and which checks are for C-code?

Thank you Andi-Bogdan Postelnicu.

-Hiral

Greetings!

We are using clang-tidy with single ‘config-file’ listing enabled tidy-checks to run for both “C++-code” and “C-code”.

We are looking for your inputs:

From list of supported clang-tidy checks, how to identify "C++-code-specific-checks" and which are "C-Code-specific-checks"? Can this be checked programmatically?

There is not a way to identify them from the command line, but each
check has an `isLanguageVersionSupported()` function that checks for
valid language options that you can use to find this information via
manual inspection.

Are “clang-analyzer-“ checks only applied to C++-code?

Not always, those come from the static analyzer (rather than
explicitly written as clang-tidy checks) and many of those apply to C
code as well as C++ code (for example, there are checks specific to
malloc/free behavior, checks for division by zero, etc).

What happens internally if C++-code-check ran on C-code? Will it skip parsing C-code?

If the check is designed to be C++-only, then it will be skipped for a
C translation unit.

~Aaron

From list of supported clang-tidy checks, how to identify "C++-code-specific-checks" and which are "C-Code-specific-checks"? Can this be checked programmatically?

There is not a way to identify them from the command line, but each check has an `isLanguageVersionSupported()` function that checks for valid language options that you can use to find this information via manual inspection.

What happens internally if C++-code-check ran on C-code? Will it skip parsing C-code?

If the check is designed to be C++-only, then it will be skipped for a C translation unit.

Ok, I could see below LangOpts checks... from "clang-tools-extra/clang-tidy/ClangTidyCheck.h" could read that 'registerPPCallbacks()' and 'registerMatchers' gets executed if the function isLanguageVersionSupported returns true.

$ grep -ri isLanguageVersionSupported llvm-project/clang-tools-extra -A5 | grep LangOpt | grep -v isLanguageVersionSupported | cut -d' ' -f4- | sort -n | uniq
const LangOptions &LangOpts) const {
(LangOpts.CPlusPlus)
LangOpts.CPlusPlus11;
RequireCPlusPlus14 ? LangOpts.CPlusPlus14 : LangOpts.CPlusPlus11;
return getLangOpts().CPlusPlus && getLangOpts().CXXExceptions;
return LangOpts.Blocks;
return LangOpts.Bool;
return LangOpts.CPlusPlus;
     return LangOpts.CPlusPlus11;
return LangOpts.CPlusPlus11;
return LangOpts.CPlusPlus11 || LangOpts.C11;
return LangOpts.CPlusPlus14;
return !LangOpts.CPlusPlus17;
return LangOpts.CPlusPlus17;
return LangOpts.CPlusPlus && LangOpts.CXXExceptions;
return LangOpts.CPlusPlus && !LangOpts.ObjC;
return LangOpts.CPlusPlus && !LangOpts.ThreadsafeStatics;
return LangOpts.ObjC;
return LangOpts.ObjC && LangOpts.ObjCAutoRefCount;
return LangOpts.OpenMP;
return LangOpts.OpenMP && LangOpts.CPlusPlus && LangOpts.CXXExceptions;

Are “clang-analyzer-“ checks only applied to C++-code?

Not always, those come from the static analyzer (rather than explicitly written as clang-tidy checks) and many of those apply to C code as well as C++ code (for example, there are checks specific to malloc/free behavior, checks for division by zero, etc).

I am seeing strange observation with clang-analyzer-* checks:
For example: if I run below command to list only single "clang-analyzer-apiModeling.StdCLibraryFunctions" but it list all other clang-analyzer-* checks too!

$ clang-tidy --version
  LLVM version 14.0.0git
  Optimized build.
  Default target: x86_64-unknown-linux-gnu

$ clang-tidy --list-checks --config-file=<path>/config-file-clang-analyzer-apiModeling.StdCLibraryFunctions
Enabled checks:
    clang-analyzer-apiModeling.StdCLibraryFunctions
    clang-analyzer-core.CallAndMessage
    clang-analyzer-core.CallAndMessageModeling
    clang-analyzer-core.DivideZero
    clang-analyzer-core.DynamicTypePropagation
    clang-analyzer-core.NonNullParamChecker
    clang-analyzer-core.NonnilStringConstants
    clang-analyzer-core.NullDereference
    clang-analyzer-core.StackAddrEscapeBase
    clang-analyzer-core.StackAddressEscape
    clang-analyzer-core.UndefinedBinaryOperatorResult
    clang-analyzer-core.VLASize
    clang-analyzer-core.builtin.BuiltinFunctions
    clang-analyzer-core.builtin.NoReturnFunctions
    clang-analyzer-core.uninitialized.ArraySubscript
    clang-analyzer-core.uninitialized.Assign
    clang-analyzer-core.uninitialized.Branch
    clang-analyzer-core.uninitialized.CapturedBlockVariable
    clang-analyzer-core.uninitialized.UndefReturn

Where,
$ cat <path>/config-file-clang-analyzer-apiModeling.StdCLibraryFunctions

>> From list of supported clang-tidy checks, how to identify "C++-code-specific-checks" and which are "C-Code-specific-checks"? Can this be checked programmatically?
>There is not a way to identify them from the command line, but each check has an `isLanguageVersionSupported()` function that checks for valid language options that you can use to find this information via manual inspection.

>> What happens internally if C++-code-check ran on C-code? Will it skip parsing C-code?
> If the check is designed to be C++-only, then it will be skipped for a C translation unit.

Ok, I could see below LangOpts checks... from "clang-tools-extra/clang-tidy/ClangTidyCheck.h" could read that 'registerPPCallbacks()' and 'registerMatchers' gets executed if the function isLanguageVersionSupported returns true.

Correct.

$ grep -ri isLanguageVersionSupported llvm-project/clang-tools-extra -A5 | grep LangOpt | grep -v isLanguageVersionSupported | cut -d' ' -f4- | sort -n | uniq
const LangOptions &LangOpts) const {
(LangOpts.CPlusPlus)
LangOpts.CPlusPlus11;
RequireCPlusPlus14 ? LangOpts.CPlusPlus14 : LangOpts.CPlusPlus11;
return getLangOpts().CPlusPlus && getLangOpts().CXXExceptions;
return LangOpts.Blocks;
return LangOpts.Bool;
return LangOpts.CPlusPlus;
     return LangOpts.CPlusPlus11;
return LangOpts.CPlusPlus11;
return LangOpts.CPlusPlus11 || LangOpts.C11;
return LangOpts.CPlusPlus14;
return !LangOpts.CPlusPlus17;
return LangOpts.CPlusPlus17;
return LangOpts.CPlusPlus && LangOpts.CXXExceptions;
return LangOpts.CPlusPlus && !LangOpts.ObjC;
return LangOpts.CPlusPlus && !LangOpts.ThreadsafeStatics;
return LangOpts.ObjC;
return LangOpts.ObjC && LangOpts.ObjCAutoRefCount;
return LangOpts.OpenMP;
return LangOpts.OpenMP && LangOpts.CPlusPlus && LangOpts.CXXExceptions;

>> Are “clang-analyzer-“ checks only applied to C++-code?
> Not always, those come from the static analyzer (rather than explicitly written as clang-tidy checks) and many of those apply to C code as well as C++ code (for example, there are checks specific to malloc/free behavior, checks for division by zero, etc).

I am seeing strange observation with clang-analyzer-* checks:
For example: if I run below command to list only single "clang-analyzer-apiModeling.StdCLibraryFunctions" but it list all other clang-analyzer-* checks too!

$ clang-tidy --version
  LLVM version 14.0.0git
  Optimized build.
  Default target: x86_64-unknown-linux-gnu

$ clang-tidy --list-checks --config-file=<path>/config-file-clang-analyzer-apiModeling.StdCLibraryFunctions
Enabled checks:
    clang-analyzer-apiModeling.StdCLibraryFunctions
    clang-analyzer-core.CallAndMessage
    clang-analyzer-core.CallAndMessageModeling
    clang-analyzer-core.DivideZero
    clang-analyzer-core.DynamicTypePropagation
    clang-analyzer-core.NonNullParamChecker
    clang-analyzer-core.NonnilStringConstants
    clang-analyzer-core.NullDereference
    clang-analyzer-core.StackAddrEscapeBase
    clang-analyzer-core.StackAddressEscape
    clang-analyzer-core.UndefinedBinaryOperatorResult
    clang-analyzer-core.VLASize
    clang-analyzer-core.builtin.BuiltinFunctions
    clang-analyzer-core.builtin.NoReturnFunctions
    clang-analyzer-core.uninitialized.ArraySubscript
    clang-analyzer-core.uninitialized.Assign
    clang-analyzer-core.uninitialized.Branch
    clang-analyzer-core.uninitialized.CapturedBlockVariable
    clang-analyzer-core.uninitialized.UndefReturn

Where,
$ cat <path>/config-file-clang-analyzer-apiModeling.StdCLibraryFunctions
---
Checks: '
-*,
-clang-analyzer-*,
-clang-analyzer-apiModeling-*,
-clang-analyzer-core-*,
-clang-analyzer-cplusplus-*,
-clang-analyzer-deadcode-*,
-clang-analyzer-fuchsia-*,
-clang-analyzer-nullability-*,
-clang-analyzer-optin-*,
-clang-analyzer-osx-*,
-clang-analyzer-security-*,
-clang-analyzer-unix-*,
-clang-analyzer-valist-*,
-clang-analyzer-apiModeling.google.GTest,
-clang-analyzer-apiModeling.llvm.CastValue,
-clang-analyzer-apiModeling.llvm.ReturnValue,
-clang-analyzer-apiModeling.StdCLibraryFunctions,
-clang-analyzer-apiModeling.TrustNonnull,
-clang-analyzer-core.builtin.BuiltinFunctions,
-clang-analyzer-core.builtin.NoReturnFunctions,
-clang-analyzer-core.CallAndMessage,
-clang-analyzer-core.DivideZero,
-clang-analyzer-core.DynamicTypePropagation,
-clang-analyzer-core.NonnilStringConstants,
-clang-analyzer-core.NonNullParamChecker,
-clang-analyzer-core.NullDereference,
-clang-analyzer-core.StackAddrEscapeBase,
-clang-analyzer-core.StackAddressEscape,
-clang-analyzer-core.UndefinedBinaryOperatorResult,
-clang-analyzer-core.uninitialized.ArraySubscript,
-clang-analyzer-core.uninitialized.Assign,
-clang-analyzer-core.uninitialized.Branch,
-clang-analyzer-core.uninitialized.CapturedBlockVariable,
-clang-analyzer-core.uninitialized.UndefReturn,
-clang-analyzer-core.VLASize,
-clang-analyzer-cplusplus.Move,
-clang-analyzer-cplusplus.PureVirtualCall,
-clang-analyzer-cplusplus.SelfAssignment,
-clang-analyzer-cplusplus.SmartPtr,
-clang-analyzer-cplusplus.VirtualCallModeling,
-clang-analyzer-nullability.NullableDereferenced,
-clang-analyzer-nullability.NullablePassedToNonnull,
-clang-analyzer-nullability.NullableReturnedFromNonnull,
-clang-analyzer-nullability.NullPassedToNonnull,
-clang-analyzer-nullability.NullReturnedFromNonnull,
-clang-analyzer-optin.mpi.MPI-Checker,
-clang-analyzer-optin.performance.GCDAntipattern,
-clang-analyzer-security.FloatLoopCounter,
-clang-analyzer-security.insecureAPI.decodeValueOfObjCType,
-clang-analyzer-security.insecureAPI.getpw,
-clang-analyzer-security.insecureAPI.gets,
-clang-analyzer-security.insecureAPI.mkstemp,
-clang-analyzer-security.insecureAPI.mktemp,
-clang-analyzer-security.insecureAPI.SecuritySyntaxChecker,
-clang-analyzer-security.insecureAPI.UncheckedReturn,
-clang-analyzer-unix.cstring.BadSizeArg,
-clang-analyzer-unix.cstring.CStringModeling,
-clang-analyzer-unix.DynamicMemoryModeling,
-clang-analyzer-valist.CopyToSelf,
-clang-analyzer-valist.ValistBase,
clang-analyzer-apiModeling.StdCLibraryFunctions'

Just enabled one "

That is interesting -- I have no idea why there's a discrepancy there
(or if it's intentional for some reason).

~Aaron

Any reference on flow of clang-analyzer-* tidy-checks?

What is diff between clang-tidy and https://clang.llvm.org/docs/ClangStaticAnalyzer.html?

Thank you.
-Hiral

Any reference on flow of clang-analyzer-* tidy-checks?

https://clang.llvm.org/extra/clang-tidy/checks/list.html

The static analyzer checks are the one listed with "Clang Static
Analyzer" in the alias column (towards the bottom of the page).

What is diff between clang-tidy and https://clang.llvm.org/docs/ClangStaticAnalyzer.html?

clang-tidy runs Clang as a library to generate an AST (which may cause
diagnostics when building the AST) and then checks run which walk the
AST looking for problematic patterns, deciding whether to diagnose or
not. The Clang Static Analyzer is another pass of Clang that can also
be run as a library, so clang-tidy can additionally run the static
analyzer checks through its interface. Rather than walking the AST
looking for patterns, the static analyzer creates a control flow graph
of the possible paths of execution the program can take and its checks
walk those flow graphs to look for problematic patterns that may be
worth diagnosing. (Roughly)

~Aaron