#!/usr/bin/env bash CHECKS="*" ERRORS="*" # Can't fix this, because winsock has different HANDLE type than posix. # Still good to occasionally look at. ERRORS="$ERRORS,-google-readability-casting" # Need to investigate or disable and document these. # ========================================================= # TODO(iphydf): Fix these. ERRORS="$ERRORS,-cert-err34-c" ERRORS="$ERRORS,-readability-suspicious-call-argument" CHECKS="$CHECKS,-cppcoreguidelines-avoid-goto,-hicpp-avoid-goto" CHECKS="$CHECKS,-bugprone-incorrect-roundings" # TODO(iphydf): Fix this by making more functions set error code enums. CHECKS="$CHECKS,-bugprone-switch-missing-default-case" # TODO(iphydf): We might want some of these. For the ones we don't want, add a # comment explaining why not. CHECKS="$CHECKS,-clang-analyzer-optin.performance.Padding" CHECKS="$CHECKS,-hicpp-signed-bitwise" # TODO(iphydf): Maybe fix these? CHECKS="$CHECKS,-bugprone-implicit-widening-of-multiplication-result" CHECKS="$CHECKS,-bugprone-integer-division" CHECKS="$CHECKS,-misc-no-recursion" # TODO(iphydf): Only happens in bootstrap_daemon. Fix it. CHECKS="$CHECKS,-cppcoreguidelines-avoid-non-const-global-variables" # TODO(iphydf): Probably fix these. CHECKS="$CHECKS,-cert-err33-c,-cppcoreguidelines-avoid-magic-numbers,-readability-magic-numbers" # Documented disabled checks. We don't want these for sure. # ========================================================= # We want to decay many arrays to pointers. In C, we do that all the time. CHECKS="$CHECKS,-cppcoreguidelines-pro-bounds-array-to-pointer-decay,-hicpp-no-array-decay" # enum{} breaks comparisons and arithmetic in C++. CHECKS="$CHECKS,-modernize-macro-to-enum" # For most things, we do want this, but for some we want to ensure (with msan) # that struct members are actually initialised with useful non-zero values. # Initialising them by default takes away that validation. CHECKS="$CHECKS,-cppcoreguidelines-pro-type-member-init,-hicpp-member-init" # https://stackoverflow.com/questions/58672959/why-does-clang-tidy-say-vsnprintf-has-an-uninitialized-va-list-argument CHECKS="$CHECKS,-clang-analyzer-valist.Uninitialized" # We pass a lot of ints around, so many function parameters are some kind of # int type that can be converted from another int type. We won't be getting # away from that anytime soon. CHECKS="$CHECKS,-bugprone-easily-swappable-parameters" # Callback handlers often don't use all their parameters. There's # IgnoreVirtual, but that doesn't work for C-style callbacks. CHECKS="$CHECKS,-misc-unused-parameters" # We sometimes use #if 0. CHECKS="$CHECKS,-readability-avoid-unconditional-preprocessor-if" # We have better macro hygiene checks with tokstyle. We can never pass macro # arguments that require parentheses inside the macro. CHECKS="$CHECKS,-bugprone-macro-parentheses" # We don't use memcpy_s. CHECKS="$CHECKS,-clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling" # __attribute__((nonnull)) causes this warning on defensive null checks. CHECKS="$CHECKS,-clang-diagnostic-pointer-bool-conversion" CHECKS="$CHECKS,-clang-diagnostic-tautological-pointer-compare" # Conflicts with "Variable is assigned a value that is never used." # [unreadVariable] CHECKS="$CHECKS,-cppcoreguidelines-init-variables" # Short variable names are used quite a lot, and we don't consider them a # readability issue. CHECKS="$CHECKS,-readability-identifier-length" # Altera checks are for GPUs (OpenCL). Our code doesn't run on GPUs. CHECKS="$CHECKS,-altera-id-dependent-backward-branch" CHECKS="$CHECKS,-altera-struct-pack-align" CHECKS="$CHECKS,-altera-unroll-loops" # We target systems other than Android, so we don't want to use non-standard # functions from the Android libc. CHECKS="$CHECKS,-android-cloexec-accept" CHECKS="$CHECKS,-android-cloexec-fopen" # This catches all the feature test macros (_POSIX_SOURCE etc.). CHECKS="$CHECKS,-bugprone-reserved-identifier" CHECKS="$CHECKS,-cert-dcl37-c" CHECKS="$CHECKS,-cert-dcl51-cpp" # Too restrictive. This makes sense if the branch clone is very large, but not # if it's a single line. It can make the code less readable. CHECKS="$CHECKS,-bugprone-branch-clone" # We intentionally send some not null-terminated strings in tests and use it for # the toxencryptsave magic number. CHECKS="$CHECKS,-bugprone-not-null-terminated-result" # We don't want default labels in enum switches. CHECKS="$CHECKS,-hicpp-multiway-paths-covered" # This can make readability quite a bit worse when the 2 cases look very # similar. CHECKS="$CHECKS,-llvm-else-after-return" CHECKS="$CHECKS,-readability-else-after-return" # We need 'return;' in empty functions because cimple won't allow empty # functions otherwise. CHECKS="$CHECKS,-readability-redundant-control-flow" # These are incredibly annoying, because things like # uint16_t a = 0, b = 1, c = a > b ? a : b; # ^ # Trip the checker, which is true, because of integer promotion, but also not # very helpful as a diagnostic. CHECKS="$CHECKS,-bugprone-narrowing-conversions,-cppcoreguidelines-narrowing-conversions" # Mistakenly thinks that # const int a = 0, b = 1; # assert(a < b); # is a constant expression in C (it is in C++ though, which is probably why it's # mistaken), suggesting to replace 'assert()' with 'static_assert()' in cases # where that won't work. # # There are ways to make 'static_assert()' work, but they are rather annoying -- # they are somewhat ugly, hurting the readability, and some are error-prone: # # - Turning 'a' and 'b' into enum constants would make it work, but this falls # apart if the enum types are compared against non-enums down the line # error: enumerated and non-enumerated type in conditional expression [-Werror=extra] # # - Turning 'a' and 'b' into pre-processor macros is the only option left, but # #defines and #undefs in the middle of a function hurt the readability and # are less idiomatic than simply using 'const int'. CHECKS="$CHECKS,-cert-dcl03-c,-hicpp-static-assert,-misc-static-assert" # Doesn't consider use of preprocessor macros as needing a header, breaking # struct definitions that depend on size macros from e.g. crypto_core.h. CHECKS="$CHECKS,-misc-include-cleaner" # A bunch of checks only valid for C++, we turn off for C. # ========================================================= # We don't use Google's int typedefs. CHECKS="$CHECKS,-google-runtime-int" # We write C code, so we use C arrays. CHECKS="$CHECKS,-cppcoreguidelines-avoid-c-arrays,-hicpp-avoid-c-arrays,-modernize-avoid-c-arrays" # C loops are ok. This one tells us to use range-for. CHECKS="$CHECKS,-modernize-loop-convert" # No auto in C. CHECKS="$CHECKS,-hicpp-use-auto,-modernize-use-auto" # Only C style casts in C. CHECKS="$CHECKS,-cppcoreguidelines-pro-type-cstyle-cast" # We use malloc (for now), and MISRA checks this too. CHECKS="$CHECKS,-cppcoreguidelines-no-malloc,-hicpp-no-malloc" # No owning_ptr<> in C. CHECKS="$CHECKS,-cppcoreguidelines-owning-memory" # void foo(void) is good in C. CHECKS="$CHECKS,-modernize-redundant-void-arg" # No using-typedefs in C. CHECKS="$CHECKS,-modernize-use-using" # No namespaces in C. CHECKS="$CHECKS,-misc-use-anonymous-namespace" # No trailing return type in C. CHECKS="$CHECKS,-modernize-use-trailing-return-type" # No and friends in C. CHECKS="$CHECKS,-hicpp-deprecated-headers,-modernize-deprecated-headers" # We use varargs for logging (we could reconsider, but right now we do). CHECKS="$CHECKS,-cppcoreguidelines-pro-type-vararg,-hicpp-vararg,-cert-dcl50-cpp" # We do want to use the array index operator, even when the index is non-constant. CHECKS="$CHECKS,-cppcoreguidelines-pro-bounds-constant-array-index" # We don't want to use pointer arithmetic, but this one includes array index # operators, which we do want to use. CHECKS="$CHECKS,-cppcoreguidelines-pro-bounds-pointer-arithmetic" # Can't use constexpr, yet. C will have it eventually, but it'll be years # until we can use it across all the compilers. CHECKS="$CHECKS,-cppcoreguidelines-macro-usage" # These are all very C++ and/or LLVM specific. CHECKS="$CHECKS,-llvmlibc-*" set -eux # TODO(iphydf): Add toxav. DIRS=( other/bootstrap_daemon/src other toxcore toxcore/events toxencryptsave ) copy_files() { find "${DIRS[@]}" \ -maxdepth 1 -type d -exec mkdir -p "$1/{}" \; find "${DIRS[@]}" \ -maxdepth 1 -name "*.[ch]" -exec cp "{}" "$1/{}" \; } run() { echo "Running clang-tidy in variant '$*'" EXTRA_ARGS=("$@") for i in "${!EXTRA_ARGS[@]}"; do EXTRA_ARGS[$i]="--extra-arg=${EXTRA_ARGS[$i]}" done ls .clang-tidy copy_files a if ! find "${DIRS[@]}" \ -maxdepth 1 -name "*.[ch]" -print0 \ | xargs -0 -n15 -P"$(nproc)" clang-tidy \ -p="$PWD/_build" \ --extra-arg=-DMIN_LOGGER_LEVEL=LOGGER_LEVEL_TRACE \ "${EXTRA_ARGS[@]}" \ --fix \ --checks="$CHECKS" \ --warnings-as-errors="$ERRORS" \ --use-color; then copy_files b colordiff -ru a b rm -rf a b false fi rm -rf a } cmake . -B_build -GNinja -DCMAKE_EXPORT_COMPILE_COMMANDS=ON sed -i -e 's/-std=c11/-xc++/' _build/compile_commands.json . other/analysis/variants.sh