FreeBSD Manual Pages
EXTRACLANGTOOLS(1) Extra Clang Tools EXTRACLANGTOOLS(1) NAME extraclangtools - Extra Clang Tools Documentation Welcome to the clang-tools-extra project which contains extra tools built using Clang's tooling APIs. EXTRA CLANG TOOLS 18.1.8 RELEASE NOTES • Introduction • What's New in Extra Clang Tools 18.1.8? • Major New Features • Improvements to clangd • Inlay hints • Compile flags • Hover • Code completion • Code actions • Signature help • Cross-references • Objective-C • Miscellaneous • Improvements to clang-doc • Improvements to clang-query • Improvements to clang-rename • Improvements to clang-tidy • New checks • New check aliases • Changes in existing checks • Removed checks • Improvements to include-cleaner • Improvements to clang-include-fixer • Improvements to modularize • Improvements to pp-trace • Clang-tidy Visual Studio plugin Written by the LLVM Team Introduction This document contains the release notes for the Extra Clang Tools, part of the Clang release 18.1.8. Here we describe the status of the Extra Clang Tools in some detail, including major improvements from the previous release and new feature work. All LLVM releases may be down- loaded from the LLVM releases web site. For more information about Clang or LLVM, including information about the latest release, please see the Clang Web Site or the LLVM Web Site. Note that if you are reading this file from a Git checkout or the main Clang web page, this document applies to the next release, not the cur- rent one. To see the release notes for a specific release, please see the releases page. What's New in Extra Clang Tools 18.1.8? Some of the major new features and improvements to Extra Clang Tools are listed here. Generic improvements to Extra Clang Tools as a whole or to its underlying infrastructure are described first, followed by tool-specific sections. Major New Features ... Improvements to clangd Inlay hints • Type hints • Improved heuristics for showing sugared vs. desguared types • Some hints which provide no information (e.g. <depen- dent-type>) are now omitted • Parameter hints • Parameter hints are now shown for calls through function pointers • Parameter hints are now shown for calls to a class's opera- tor() • No longer show bogus parameter hints for some builtins like __builtin_dump_struct Compile flags • System include extractor (--query-driver) improvements • The directory containing builtin headers is now excluded from extracted system includes • Various flags which can affect the system includes (--tar- get, --stdlib, -specs) are now forwarded to the driver • Fixed a bug where clangd would sometimes try to call a dri- ver that didn't have obj-c support with -x objec- tive-c++-header • The driver path is now dot-normalized before being compared to the --query-driver pattern • --query-driver is now supported by clangd-indexer • Fixed a regression in clangd 17 where response files would not be ex- panded Hover • Hover now shows alignment info for fields and records Code completion • Refined heuristics for determining whether the use of a function can be a call or not Code actions • The extract variable tweak gained support for extracting lambda ex- pressions to a variable. • A new tweak was added for turning unscoped into scoped enums. Signature help • Improved support for calls through function pointer types Cross-references • Improved support for C++20 concepts • Find-references now works for labels • Improvements to template heuristics Objective-C Miscellaneous • Various stability improvements, e.g. crash fixes • Improved error recovery on invalid code • Clangd now bails gracefully on assembly and IR source files Improvements to clang-doc Improvements to clang-query The improvements are... Improvements to clang-rename The improvements are... Improvements to clang-tidy • Preprocessor-level module header parsing is now disabled by default due to the problems it caused in C++20 and above, leading to perfor- mance and code parsing issues regardless of whether modules were used or not. This change will impact only the following checks: modernize-replace-disallow-copy-and-assign-macro, bugprone-reserved-identifier, and readability-identifier-naming. Those checks will no longer see macros defined in modules. Users can still enable this functionality using the newly added command line option --enable-module-headers-parsing. • Remove configuration option AnalyzeTemporaryDestructors, which was deprecated since clang-tidy 16. • Improved --dump-config to print check options in alphabetical order. • Improved clang-tidy-diff.py script. • Return exit code 1 if any clang-tidy subprocess exits with a non-zero code or if exporting fixes fails. • Accept a directory as a value for -export-fixes to export individual yaml files for each compilation unit. • Introduce a -config-file option that forwards a configura- tion file to clang-tidy. Corresponds to the --config-file option in clang-tidy. • Improved run-clang-tidy.py script. It now accepts a directory as a value for -export-fixes to export individual yaml files for each com- pilation unit. New checks • New bugprone-casting-through-void check. Detects unsafe or redundant two-step casting operations involving void*. • New bugprone-chained-comparison check. Check detects chained comparison operators that can lead to unin- tended behavior or logical errors. • New bugprone-compare-pointer-to-member-virtual-function check. Detects equality comparison between pointer to member virtual func- tion and anything other than null-pointer-constant. • New bugprone-inc-dec-in-conditions check. Detects when a variable is both incremented/decremented and refer- enced inside a complex condition and suggests moving them outside to avoid ambiguity in the variable's value. • New bugprone-incorrect-enable-if check. Detects incorrect usages of std::enable_if that don't name the nested type type. • New bugprone-multi-level-implicit-pointer-conversion check. Detects implicit conversions between pointers of different levels of indirection. • New bugprone-optional-value-conversion check. Detects potentially unintentional and redundant conversions where a value is extracted from an optional-like type and then used to create a new instance of the same optional-like type. • New bugprone-unused-local-non-trivial-variable check. Warns when a local non trivial variable is unused within a function. • New cppcoreguidelines-no-suspend-with-lock check. Flags coroutines that suspend while a lock guard is in scope at the suspension point. • New hicpp-ignored-remove-result check. Ensure that the result of std::remove, std::remove_if and std::unique are not ignored according to rule 17.5.1. • New misc-coroutine-hostile-raii check. Detects when objects of certain hostile RAII types persists across suspension points in a coroutine. Such hostile types include scoped-lockable types and types belonging to a configurable denylist. • New modernize-use-constraints check. Replace enable_if with C++20 requires clauses. • New modernize-use-starts-ends-with check. Checks whether a find or rfind result is compared with 0 and suggests replacing with starts_with when the method exists in the class. No- tably, this will work with std::string and std::string_view. • New modernize-use-std-numbers check. Finds constants and function calls to math functions that can be re- placed with C++20's mathematical constants from the numbers header and offers fix-it hints. • New performance-enum-size check. Recommends the smallest possible underlying type for an enum or enum class based on the range of its enumerators. • New readability-avoid-nested-conditional-operator check. Identifies instances of nested conditional operators in the code. • New readability-avoid-return-with-void-value check. Finds return statements with void values used within functions with void result types. • New readability-redundant-casting check. Detects explicit type casting operations that involve the same source and destination types, and subsequently recommend their removal. • New readability-redundant-inline-specifier check. Detects redundant inline specifiers on function and variable declara- tions. • New readability-reference-to-constructed-temporary check. Detects C++ code where a reference variable is used to extend the lifetime of a temporary object that has just been constructed. New check aliases • New alias cppcoreguidelines-macro-to-enum to modernize-macro-to-enum was added. Changes in existing checks • Improved abseil-string-find-startswith check to also consider std::basic_string_view in addition to std::basic_string by default. • Improved bugprone-assert-side-effect check to report usage of non-const << and >> operators in assertions and fixed some false-pos- itives with const operators. • Improved bugprone-dangling-handle check to support functional casting during type conversions at variable initialization, now with improved compatibility for C++17 and later versions. • Improved bugprone-exception-escape check by extending the default check function names to include iter_swap and iter_move. • Improved bugprone-implicit-widening-of-multiplication-result check to correctly emit fixes. • Improved bugprone-lambda-function-name check by adding option Ig- noreMacros to ignore warnings in macros. • Improved bugprone-non-zero-enum-to-bool-conversion check by eliminat- ing false positives resulting from direct usage of bitwise operators. • Improved bugprone-reserved-identifier check, so that it does not warn on macros starting with underscore and lowercase letter. • Improved bugprone-sizeof-expression check diagnostics to precisely highlight specific locations, providing more accurate guidance. • Improved bugprone-unchecked-optional-access check, so that it does not crash during handling of optional values. • Improved bugprone-undefined-memory-manipulation check to support fixed-size arrays of non-trivial types. • Improved bugprone-unused-return-value check diagnostic message, added support for detection of unused results when cast to non-void type. Casting to void no longer suppresses issues by default, control this behavior with the new AllowCastToVoid option. • Improved cppcoreguidelines-avoid-non-const-global-variables check to ignore static variables declared within the scope of class/struct. • Improved cppcoreguidelines-avoid-reference-coroutine-parameters check to ignore false positives related to matching parameters of non coroutine functions and increase issue detection for cases involving type aliases with references. • Improved cppcoreguidelines-missing-std-forward check to address false positives in the capture list and body of lambdas. • Improved cppcoreguidelines-narrowing-conversions check by extending the IgnoreConversionFromTypes option to include types without a dec- laration, such as built-in types. • Improved cppcoreguidelines-prefer-member-initializer check to ignore delegate constructors and ignore re-assignment for reference or when initialization depend on field that is initialized before. Addition- ally, it now provides valid fixes for member variables initialized with macros. • Improved cppcoreguidelines-pro-bounds-array-to-pointer-decay check to ignore predefined expression (e.g., __func__, ...). • Improved cppcoreguidelines-pro-bounds-constant-array-index check to perform checks on derived classes of std::array. • Improved cppcoreguidelines-pro-type-const-cast check to ignore casts to const or volatile type (controlled by StrictMode option) and casts in implicitly invoked code. • Improved cppcoreguidelines-pro-type-member-init check to ignore de- pendent delegate constructors. • Improved cppcoreguidelines-pro-type-static-cast-downcast check to disregard casts on non-polymorphic types when the StrictMode option is set to false. • Improved cppcoreguidelines-pro-type-vararg check to ignore false-pos- itives in unevaluated context (e.g., decltype, sizeof, ...). • Improved cppcoreguidelines-rvalue-reference-param-not-moved check to ignore unused parameters when they are marked as unused and parame- ters of deleted functions and constructors. • Improved google-readability-casting check to ignore constructor calls disguised as functional casts. • Improved google-runtime-int check to ignore false positives on user defined-literals. • Improved llvm-namespace-comment check to provide fixes for inline namespaces in the same format as clang-format. • Improved llvmlibc-callee-namespace to support customizable namespace. This matches the change made to implementation in namespace. • Improved llvmlibc-implementation-in-namespace to support customizable namespace. This further allows for testing the libc when the sys- tem-libc is also LLVM's libc. • Improved llvmlibc-inline-function-decl to properly ignore implicit functions, such as struct constructors, and explicitly deleted func- tions. • Improved misc-const-correctness check to avoid false positive when using pointer to member function. Additionally, the check no longer emits a diagnostic when a variable that is not type-dependent is an operand of a type-dependent binary operator. Improved performance of the check through optimizations. The check no longer emits a diagnos- tic for non-parameter-pack variables in C++17 fold expressions. • Improved misc-include-cleaner check by adding option DeduplicateFind- ings to output one finding per symbol occurrence, avoid inserting the same header multiple times, fix a bug where IgnoreHeaders option won't work with verbatim/std headers. • Improved misc-redundant-expression check to ignore false-positives in unevaluated context (e.g., decltype). • Improved misc-static-assert check to ignore false-positives when re- ferring to non-constexpr variables in non-unevaluated context. • Improved misc-unused-using-decls check to avoid false positive when using in elaborated type and only check C++ files. • Improved modernize-avoid-bind check to not emit a return for fixes when the function returns void and to provide valid fixes for cases involving bound C++ operators. • Improved modernize-loop-convert to support for-loops with iterators initialized by free functions like begin, end, or size and avoid crash for array of dependent array and non-dereferenceable builtin types used as iterators. • Improved modernize-make-shared check to support std::shared_ptr im- plementations that inherit the reset method from a base class. • Improved modernize-return-braced-init-list check to ignore false-pos- itives when constructing the container with count copies of elements with value value. • Improved modernize-use-auto to avoid create incorrect fix hints for pointer to array type and pointer to function type. • Improved modernize-use-emplace to not replace aggregates that emplace cannot construct with aggregate initialization. • Improved modernize-use-equals-delete check to ignore false-positives when special member function is actually used or implicit. • Improved modernize-use-nullptr check by adding option IgnoredTypes that can be used to exclude some pointer types. • Improved modernize-use-std-print check to accurately generate fixes for reordering arguments. • Improved modernize-use-using check to fix function pointer and for- ward declared typedef correctly. Added option IgnoreExternC to ignore typedef declaration in extern "C" scope. • Improved performance-faster-string-find check to properly escape sin- gle quotes. • Improved performance-for-range-copy check to handle cases where the loop variable is a structured binding. • Improved performance-noexcept-move-constructor to better handle con- ditional noexcept expressions, eliminating false-positives. • Improved performance-noexcept-swap check to enforce a stricter match with the swap function signature and better handling of condition noexcept expressions, eliminating false-positives. iter_swap function name is checked by default. • Improved readability-braces-around-statements check to ignore false-positive for if constexpr in lambda expression. • Improved readability-avoid-const-params-in-decls diagnostics to high- light the const location • Improved readability-container-contains to correctly handle integer literals with suffixes in fix-its. • Improved readability-container-size-empty check to detect comparison between string and empty string literals and support length() method as an alternative to size(). Resolved false positives tied to nega- tive values from size-like methods, and one triggered by size checks below zero. • Improved readability-function-size check configuration to use none rather than -1 to disable some parameters. • Improved readability-identifier-naming check to issue accurate warn- ings when a type's forward declaration precedes its definition. Ad- ditionally, it now provides appropriate warnings for struct and union in C, while also incorporating support for the Leading_up- per_snake_case naming convention. The handling of typedef has been enhanced, particularly within complex types like function pointers and cases where style checks were omitted when functions started with macros. Added support for C++20 concept declarations. Camel_Snake_Case and camel_Snake_Case now detect more invalid identi- fier names. Fields in anonymous records (i.e. anonymous structs and unions) now can be checked with the naming rules associated with their enclosing scopes rather than the naming rules of public struct/union members. • Improved readability-implicit-bool-conversion check to take do-while loops into account for the AllowIntegerConditions and AllowPointer- Conditions options. It also now provides more consistent suggestions when parentheses are added to the return value or expressions. It also ignores false-positives for comparison containing bool bitfield. • Improved readability-misleading-indentation check to ignore false-positives for line started with empty macro. • Improved readability-non-const-parameter check to ignore false-posi- tives in initializer list of record. • Improved readability-redundant-member-init check to now also detect redundant in-class initializers. • Improved readability-simplify-boolean-expr check by adding the new option IgnoreMacros that allows to ignore boolean expressions origi- nating from expanded macros. • Improved readability-simplify-subscript-expr check by extending the default value of the Types option to include std::span. • Improved readability-static-accessed-through-instance check to iden- tify calls to static member functions with out-of-class inline defin- itions. Removed checks Improvements to include-cleaner • Support for --only-headers flag to limit analysis to headers matching a regex • Recognizes references through `` concept``s • Builtin headers are not analyzed • Handling of references through friend declarations • Fixes around handling of IWYU pragmas on stdlib headers • Improved handling around references to/from template specializations Improvements to clang-include-fixer The improvements are... Improvements to modularize The improvements are... Improvements to pp-trace Clang-tidy Visual Studio plugin CLANG-TIDY Contents • Clang-Tidy • Using clang-tidy • Suppressing Undesired Diagnostics See also: Clang-Tidy Checks abseil-cleanup-ctad Suggests switching the initialization pattern of absl::Cleanup in- stances from the factory function to class template argument deduction (CTAD), in C++17 and higher. auto c1 = absl::MakeCleanup([] {}); const auto c2 = absl::MakeCleanup(std::function<void()>([] {})); becomes absl::Cleanup c1 = [] {}; const absl::Cleanup c2 = std::function<void()>([] {}); abseil-duration-addition Check for cases where addition should be performed in the absl::Time domain. When adding two values, and one is known to be an absl::Time, we can infer that the other should be interpreted as an absl::Duration of a similar scale, and make that inference explicit. Examples: // Original - Addition in the integer domain int x; absl::Time t; int result = absl::ToUnixSeconds(t) + x; // Suggestion - Addition in the absl::Time domain int result = absl::ToUnixSeconds(t + absl::Seconds(x)); abseil-duration-comparison Checks for comparisons which should be in the absl::Duration domain in- stead of the floating point or integer domains. N.B.: In cases where a Duration was being converted to an integer and then compared against a floating-point value, truncation during the Du- ration conversion might yield a different result. In practice this is very rare, and still indicates a bug which should be fixed. Examples: // Original - Comparison in the floating point domain double x; absl::Duration d; if (x < absl::ToDoubleSeconds(d)) ... // Suggested - Compare in the absl::Duration domain instead if (absl::Seconds(x) < d) ... // Original - Comparison in the integer domain int x; absl::Duration d; if (x < absl::ToInt64Microseconds(d)) ... // Suggested - Compare in the absl::Duration domain instead if (absl::Microseconds(x) < d) ... abseil-duration-conversion-cast Checks for casts of absl::Duration conversion functions, and recommends the right conversion function instead. Examples: // Original - Cast from a double to an integer absl::Duration d; int i = static_cast<int>(absl::ToDoubleSeconds(d)); // Suggested - Use the integer conversion function directly. int i = absl::ToInt64Seconds(d); // Original - Cast from a double to an integer absl::Duration d; double x = static_cast<double>(absl::ToInt64Seconds(d)); // Suggested - Use the integer conversion function directly. double x = absl::ToDoubleSeconds(d); Note: In the second example, the suggested fix could yield a different result, as the conversion to integer could truncate. In practice, this is very rare, and you should use absl::Trunc to perform this operation explicitly instead. abseil-duration-division absl::Duration arithmetic works like it does with integers. That means that division of two absl::Duration objects returns an int64 with any fractional component truncated toward 0. See this link for more infor- mation on arithmetic with absl::Duration. For example: absl::Duration d = absl::Seconds(3.5); int64 sec1 = d / absl::Seconds(1); // Truncates toward 0. int64 sec2 = absl::ToInt64Seconds(d); // Equivalent to division. assert(sec1 == 3 && sec2 == 3); double dsec = d / absl::Seconds(1); // WRONG: Still truncates toward 0. assert(dsec == 3.0); If you want floating-point division, you should use either the absl::FDivDuration() function, or one of the unit conversion functions such as absl::ToDoubleSeconds(). For example: absl::Duration d = absl::Seconds(3.5); double dsec1 = absl::FDivDuration(d, absl::Seconds(1)); // GOOD: No truncation. double dsec2 = absl::ToDoubleSeconds(d); // GOOD: No truncation. assert(dsec1 == 3.5 && dsec2 == 3.5); This check looks for uses of absl::Duration division that is done in a floating-point context, and recommends the use of a function that re- turns a floating-point value. abseil-duration-factory-float Checks for cases where the floating-point overloads of various absl::Duration factory functions are called when the more-efficient in- teger versions could be used instead. This check will not suggest fixes for literals which contain fractional floating point values or non-literals. It will suggest removing super- fluous casts. Examples: // Original - Providing a floating-point literal. absl::Duration d = absl::Seconds(10.0); // Suggested - Use an integer instead. absl::Duration d = absl::Seconds(10); // Original - Explicitly casting to a floating-point type. absl::Duration d = absl::Seconds(static_cast<double>(10)); // Suggested - Remove the explicit cast absl::Duration d = absl::Seconds(10); abseil-duration-factory-scale Checks for cases where arguments to absl::Duration factory functions are scaled internally and could be changed to a different factory func- tion. This check also looks for arguments with a zero value and sug- gests using absl::ZeroDuration() instead. Examples: // Original - Internal multiplication. int x; absl::Duration d = absl::Seconds(60 * x); // Suggested - Use absl::Minutes instead. absl::Duration d = absl::Minutes(x); // Original - Internal division. int y; absl::Duration d = absl::Milliseconds(y / 1000.); // Suggested - Use absl:::Seconds instead. absl::Duration d = absl::Seconds(y); // Original - Zero-value argument. absl::Duration d = absl::Hours(0); // Suggested = Use absl::ZeroDuration instead absl::Duration d = absl::ZeroDuration(); abseil-duration-subtraction Checks for cases where subtraction should be performed in the absl::Du- ration domain. When subtracting two values, and the first one is known to be a conversion from absl::Duration, we can infer that the second should also be interpreted as an absl::Duration, and make that infer- ence explicit. Examples: // Original - Subtraction in the double domain double x; absl::Duration d; double result = absl::ToDoubleSeconds(d) - x; // Suggestion - Subtraction in the absl::Duration domain instead double result = absl::ToDoubleSeconds(d - absl::Seconds(x)); // Original - Subtraction of two Durations in the double domain absl::Duration d1, d2; double result = absl::ToDoubleSeconds(d1) - absl::ToDoubleSeconds(d2); // Suggestion - Subtraction in the absl::Duration domain instead double result = absl::ToDoubleSeconds(d1 - d2); Note: As with other clang-tidy checks, it is possible that multiple fixes may overlap (as in the case of nested expressions), so not all occurrences can be transformed in one run. In particular, this may oc- cur for nested subtraction expressions. Running clang-tidy multiple times will find and fix these overlaps. abseil-duration-unnecessary-conversion Finds and fixes cases where absl::Duration values are being converted to numeric types and back again. Floating-point examples: // Original - Conversion to double and back again absl::Duration d1; absl::Duration d2 = absl::Seconds(absl::ToDoubleSeconds(d1)); // Suggestion - Remove unnecessary conversions absl::Duration d2 = d1; // Original - Division to convert to double and back again absl::Duration d2 = absl::Seconds(absl::FDivDuration(d1, absl::Seconds(1))); // Suggestion - Remove division and conversion absl::Duration d2 = d1; Integer examples: // Original - Conversion to integer and back again absl::Duration d1; absl::Duration d2 = absl::Hours(absl::ToInt64Hours(d1)); // Suggestion - Remove unnecessary conversions absl::Duration d2 = d1; // Original - Integer division followed by conversion absl::Duration d2 = absl::Seconds(d1 / absl::Seconds(1)); // Suggestion - Remove division and conversion absl::Duration d2 = d1; Unwrapping scalar operations: // Original - Multiplication by a scalar absl::Duration d1; absl::Duration d2 = absl::Seconds(absl::ToInt64Seconds(d1) * 2); // Suggestion - Remove unnecessary conversion absl::Duration d2 = d1 * 2; Note: Converting to an integer and back to an absl::Duration might be a truncating operation if the value is not aligned to the scale of con- version. In the rare case where this is the intended result, callers should use absl::Trunc to truncate explicitly. abseil-faster-strsplit-delimiter Finds instances of absl::StrSplit() or absl::MaxSplits() where the de- limiter is a single character string literal and replaces with a char- acter. The check will offer a suggestion to change the string literal into a character. It will also catch code using absl::ByAnyChar() for just a single character and will transform that into a single character as well. These changes will give the same result, but using characters rather than single character string literals is more efficient and readable. Examples: // Original - the argument is a string literal. for (auto piece : absl::StrSplit(str, "B")) { // Suggested - the argument is a character, which causes the more efficient // overload of absl::StrSplit() to be used. for (auto piece : absl::StrSplit(str, 'B')) { // Original - the argument is a string literal inside absl::ByAnyChar call. for (auto piece : absl::StrSplit(str, absl::ByAnyChar("B"))) { // Suggested - the argument is a character, which causes the more efficient // overload of absl::StrSplit() to be used and we do not need absl::ByAnyChar // anymore. for (auto piece : absl::StrSplit(str, 'B')) { // Original - the argument is a string literal inside absl::MaxSplits call. for (auto piece : absl::StrSplit(str, absl::MaxSplits("B", 1))) { // Suggested - the argument is a character, which causes the more efficient // overload of absl::StrSplit() to be used. for (auto piece : absl::StrSplit(str, absl::MaxSplits('B', 1))) { abseil-no-internal-dependencies Warns if code using Abseil depends on internal details. If something is in a namespace that includes the word "internal", code is not allowed to depend upon it because it's an implementation detail. They cannot friend it, include it, you mention it or refer to it in any way. Doing so violates Abseil's compatibility guidelines and may result in break- age. See https://abseil.io/about/compatibility for more information. The following cases will result in warnings: absl::strings_internal::foo(); // warning triggered on this line class foo { friend struct absl::container_internal::faa; // warning triggered on this line }; absl::memory_internal::MakeUniqueResult(); // warning triggered on this line abseil-no-namespace Ensures code does not open namespace absl as that violates Abseil's compatibility guidelines. Code should not open namespace absl as that conflicts with Abseil's compatibility guidelines and may result in breakage. Any code that uses: namespace absl { ... } will be prompted with a warning. See the full Abseil compatibility guidelines for more information. abseil-redundant-strcat-calls Suggests removal of unnecessary calls to absl::StrCat when the result is being passed to another call to absl::StrCat or absl::StrAppend. The extra calls cause unnecessary temporary strings to be constructed. Removing them makes the code smaller and faster. Examples: std::string s = absl::StrCat("A", absl::StrCat("B", absl::StrCat("C", "D"))); //before std::string s = absl::StrCat("A", "B", "C", "D"); //after absl::StrAppend(&s, absl::StrCat("E", "F", "G")); //before absl::StrAppend(&s, "E", "F", "G"); //after abseil-str-cat-append Flags uses of absl::StrCat() to append to a std::string. Suggests absl::StrAppend() should be used instead. The extra calls cause unnecessary temporary strings to be constructed. Removing them makes the code smaller and faster. a = absl::StrCat(a, b); // Use absl::StrAppend(&a, b) instead. Does not diagnose cases where absl::StrCat() is used as a template ar- gument for a functor. abseil-string-find-startswith Checks whether a std::string::find() or std::string::rfind() (and cor- responding std::string_view methods) result is compared with 0, and suggests replacing with absl::StartsWith(). This is both a readability and performance issue. starts_with was added as a built-in function on those types in C++20. If available, prefer enabling modernize-use-starts-ends-with instead of this check. string s = "..."; if (s.find("Hello World") == 0) { /* do something */ } if (s.rfind("Hello World", 0) == 0) { /* do something */ } becomes string s = "..."; if (absl::StartsWith(s, "Hello World")) { /* do something */ } if (absl::StartsWith(s, "Hello World")) { /* do something */ } Options StringLikeClasses Semicolon-separated list of names of string-like classes. By de- fault both std::basic_string and std::basic_string_view are con- sidered. The list of methods to be considered is fixed. IncludeStyle A string specifying which include-style is used, llvm or google. Default is llvm. AbseilStringsMatchHeader The location of Abseil's strings/match.h. Defaults to absl/strings/match.h. abseil-string-find-str-contains Finds s.find(...) == string::npos comparisons (for various string-like types) and suggests replacing with absl::StrContains(). This improves readability and reduces the likelihood of accidentally mixing find() and npos from different string-like types. By default, "string-like types" includes ::std::basic_string, ::std::basic_string_view, and ::absl::string_view. See the StringLike- Classes option to change this. std::string s = "..."; if (s.find("Hello World") == std::string::npos) { /* do something */ } absl::string_view a = "..."; if (absl::string_view::npos != a.find("Hello World")) { /* do something */ } becomes std::string s = "..."; if (!absl::StrContains(s, "Hello World")) { /* do something */ } absl::string_view a = "..."; if (absl::StrContains(a, "Hello World")) { /* do something */ } Options StringLikeClasses Semicolon-separated list of names of string-like classes. By de- fault includes ::std::basic_string, ::std::basic_string_view, and ::absl::string_view. IncludeStyle A string specifying which include-style is used, llvm or google. Default is llvm. AbseilStringsMatchHeader The location of Abseil's strings/match.h. Defaults to absl/strings/match.h. abseil-time-comparison Prefer comparisons in the absl::Time domain instead of the integer do- main. N.B.: In cases where an absl::Time is being converted to an integer, alignment may occur. If the comparison depends on this alignment, doing the comparison in the absl::Time domain may yield a different result. In practice this is very rare, and still indicates a bug which should be fixed. Examples: // Original - Comparison in the integer domain int x; absl::Time t; if (x < absl::ToUnixSeconds(t)) ... // Suggested - Compare in the absl::Time domain instead if (absl::FromUnixSeconds(x) < t) ... abseil-time-subtraction Finds and fixes absl::Time subtraction expressions to do subtraction in the Time domain instead of the numeric domain. There are two cases of Time subtraction in which deduce additional type information: • When the result is an absl::Duration and the first argument is an absl::Time. • When the second argument is a absl::Time. In the first case, we must know the result of the operation, since without that the second operand could be either an absl::Time or an absl::Duration. In the second case, the first operand must be an absl::Time, because subtracting an absl::Time from an absl::Duration is not defined. Examples: int x; absl::Time t; // Original - absl::Duration result and first operand is an absl::Time. absl::Duration d = absl::Seconds(absl::ToUnixSeconds(t) - x); // Suggestion - Perform subtraction in the Time domain instead. absl::Duration d = t - absl::FromUnixSeconds(x); // Original - Second operand is an absl::Time. int i = x - absl::ToUnixSeconds(t); // Suggestion - Perform subtraction in the Time domain instead. int i = absl::ToInt64Seconds(absl::FromUnixSeconds(x) - t); abseil-upgrade-duration-conversions Finds calls to absl::Duration arithmetic operators and factories whose argument needs an explicit cast to continue compiling after upcoming API changes. The operators *=, /=, *, and / for absl::Duration currently accept an argument of class type that is convertible to an arithmetic type. Such a call currently converts the value to an int64_t, even in a case such as std::atomic<float> that would result in lossy conversion. Additionally, the absl::Duration factory functions (absl::Hours, absl::Minutes, etc) currently accept an int64_t or a floating-point type. Similar to the arithmetic operators, calls with an argument of class type that is convertible to an arithmetic type go through the int64_t path. These operators and factories will be changed to only accept arithmetic types to prevent unintended behavior. After these changes are released, passing an argument of class type will no longer compile, even if the type is implicitly convertible to an arithmetic type. Here are example fixes created by this check: std::atomic<int> a; absl::Duration d = absl::Milliseconds(a); d *= a; becomes std::atomic<int> a; absl::Duration d = absl::Milliseconds(static_cast<int64_t>(a)); d *= static_cast<int64_t>(a); Note that this check always adds a cast to int64_t in order to preserve the current behavior of user code. It is possible that this uncovers unintended behavior due to types implicitly convertible to a float- ing-point type. altera-id-dependent-backward-branch Finds ID-dependent variables and fields that are used within loops. This causes branches to occur inside the loops, and thus leads to per- formance degradation. // The following code will produce a warning because this ID-dependent // variable is used in a loop condition statement. int ThreadID = get_local_id(0); // The following loop will produce a warning because the loop condition // statement depends on an ID-dependent variable. for (int i = 0; i < ThreadID; ++i) { std::cout << i << std::endl; } // The following loop will not produce a warning, because the ID-dependent // variable is not used in the loop condition statement. for (int i = 0; i < 100; ++i) { std::cout << ThreadID << std::endl; } Based on the Altera SDK for OpenCL: Best Practices Guide. altera-kernel-name-restriction Finds kernel files and include directives whose filename is kernel.cl, Verilog.cl, or VHDL.cl. The check is case insensitive. Such kernel file names cause the offline compiler to generate interme- diate design files that have the same names as certain internal files, which leads to a compilation error. Based on the Guidelines for Naming the Kernel section in the Intel FPGA SDK for OpenCL Pro Edition: Programming Guide. altera-single-work-item-barrier Finds OpenCL kernel functions that call a barrier function but do not call an ID function (get_local_id, get_local_id, get_group_id, or get_local_linear_id). These kernels may be viable single work-item kernels, but will be forced to execute as NDRange kernels if using a newer version of the Altera Offline Compiler (>= v17.01). If using an older version of the Altera Offline Compiler, these kernel functions will be treated as single work-item kernels, which could be inefficient or lead to errors if NDRange semantics were intended. Based on the Altera SDK for OpenCL: Best Practices Guide. Examples: // error: function calls barrier but does not call an ID function. void __kernel barrier_no_id(__global int * foo, int size) { for (int i = 0; i < 100; i++) { foo[i] += 5; } barrier(CLK_GLOBAL_MEM_FENCE); } // ok: function calls barrier and an ID function. void __kernel barrier_with_id(__global int * foo, int size) { for (int i = 0; i < 100; i++) { int tid = get_global_id(0); foo[tid] += 5; } barrier(CLK_GLOBAL_MEM_FENCE); } // ok with AOC Version 17.01: the reqd_work_group_size turns this into // an NDRange. __attribute__((reqd_work_group_size(2,2,2))) void __kernel barrier_with_id(__global int * foo, int size) { for (int i = 0; i < 100; i++) { foo[tid] += 5; } barrier(CLK_GLOBAL_MEM_FENCE); } Options AOCVersion Defines the version of the Altera Offline Compiler. Defaults to 1600 (corresponding to version 16.00). altera-struct-pack-align Finds structs that are inefficiently packed or aligned, and recommends packing and/or aligning of said structs as needed. Structs that are not packed take up more space than they should, and accessing structs that are not well aligned is inefficient. Fix-its are provided to fix both of these issues by inserting and/or amending relevant struct attributes. Based on the Altera SDK for OpenCL: Best Practices Guide. // The following struct is originally aligned to 4 bytes, and thus takes up // 12 bytes of memory instead of 10. Packing the struct will make it use // only 10 bytes of memory, and aligning it to 16 bytes will make it // efficient to access. struct example { char a; // 1 byte double b; // 8 bytes char c; // 1 byte }; // The following struct is arranged in such a way that packing is not needed. // However, it is aligned to 4 bytes instead of 8, and thus needs to be // explicitly aligned. struct implicitly_packed_example { char a; // 1 byte char b; // 1 byte char c; // 1 byte char d; // 1 byte int e; // 4 bytes }; // The following struct is explicitly aligned and packed. struct good_example { char a; // 1 byte double b; // 8 bytes char c; // 1 byte } __attribute__((packed)) __attribute__((aligned(16)); // Explicitly aligning a struct to the wrong value will result in a warning. // The following example should be aligned to 16 bytes, not 32. struct badly_aligned_example { char a; // 1 byte double b; // 8 bytes char c; // 1 byte } __attribute__((packed)) __attribute__((aligned(32))); altera-unroll-loops Finds inner loops that have not been unrolled, as well as fully un- rolled loops with unknown loop bounds or a large number of iterations. Unrolling inner loops could improve the performance of OpenCL kernels. However, if they have unknown loop bounds or a large number of itera- tions, they cannot be fully unrolled, and should be partially unrolled. Notes: • This check is unable to determine the number of iterations in a while or do..while loop; hence if such a loop is fully unrolled, a note is emitted advising the user to partially unroll instead. • In for loops, our check only works with simple arithmetic increments ( +, -, *, /). For all other increments, partial unrolling is ad- vised. • Depending on the exit condition, the calculations for determining if the number of iterations is large may be off by 1. This should not be an issue since the cut-off is generally arbitrary. Based on the Altera SDK for OpenCL: Best Practices Guide. for (int i = 0; i < 10; i++) { // ok: outer loops should not be unrolled int j = 0; do { // warning: this inner do..while loop should be unrolled j++; } while (j < 15); int k = 0; #pragma unroll while (k < 20) { // ok: this inner loop is already unrolled k++; } } int A[1000]; #pragma unroll // warning: this loop is large and should be partially unrolled for (int a : A) { printf("%d", a); } #pragma unroll 5 // ok: this loop is large, but is partially unrolled for (int a : A) { printf("%d", a); } #pragma unroll // warning: this loop is large and should be partially unrolled for (int i = 0; i < 1000; ++i) { printf("%d", i); } #pragma unroll 5 // ok: this loop is large, but is partially unrolled for (int i = 0; i < 1000; ++i) { printf("%d", i); } #pragma unroll // warning: << operator not supported, recommend partial unrolling for (int i = 0; i < 1000; i<<1) { printf("%d", i); } std::vector<int> someVector (100, 0); int i = 0; #pragma unroll // note: loop may be large, recommend partial unrolling while (i < someVector.size()) { someVector[i]++; } #pragma unroll // note: loop may be large, recommend partial unrolling while (true) { printf("In loop"); } #pragma unroll 5 // ok: loop may be large, but is partially unrolled while (i < someVector.size()) { someVector[i]++; } Options MaxLoopIterations Defines the maximum number of loop iterations that a fully un- rolled loop can have. By default, it is set to 100. In practice, this refers to the integer value of the upper bound within the loop statement's condition expression. android-cloexec-accept The usage of accept() is not recommended, it's better to use accept4(). Without this flag, an opened sensitive file descriptor would remain open across a fork+exec to a lower-privileged SELinux domain. Examples: accept(sockfd, addr, addrlen); // becomes accept4(sockfd, addr, addrlen, SOCK_CLOEXEC); android-cloexec-accept4 accept4() should include SOCK_CLOEXEC in its type argument to avoid the file descriptor leakage. Without this flag, an opened sensitive file would remain open across a fork+exec to a lower-privileged SELinux do- main. Examples: accept4(sockfd, addr, addrlen, SOCK_NONBLOCK); // becomes accept4(sockfd, addr, addrlen, SOCK_NONBLOCK | SOCK_CLOEXEC); android-cloexec-creat The usage of creat() is not recommended, it's better to use open(). Examples: int fd = creat(path, mode); // becomes int fd = open(path, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, mode); android-cloexec-dup The usage of dup() is not recommended, it's better to use fcntl(), which can set the close-on-exec flag. Otherwise, an opened sensitive file would remain open across a fork+exec to a lower-privileged SELinux domain. Examples: int fd = dup(oldfd); // becomes int fd = fcntl(oldfd, F_DUPFD_CLOEXEC); android-cloexec-epoll-create The usage of epoll_create() is not recommended, it's better to use epoll_create1(), which allows close-on-exec. Examples: epoll_create(size); // becomes epoll_create1(EPOLL_CLOEXEC); android-cloexec-epoll-create1 epoll_create1() should include EPOLL_CLOEXEC in its type argument to avoid the file descriptor leakage. Without this flag, an opened sensi- tive file would remain open across a fork+exec to a lower-privileged SELinux domain. Examples: epoll_create1(0); // becomes epoll_create1(EPOLL_CLOEXEC); android-cloexec-fopen fopen() should include e in their mode string; so re would be valid. This is equivalent to having set FD_CLOEXEC on that descriptor. Examples: fopen("fn", "r"); // becomes fopen("fn", "re"); android-cloexec-inotify-init The usage of inotify_init() is not recommended, it's better to use ino- tify_init1(). Examples: inotify_init(); // becomes inotify_init1(IN_CLOEXEC); android-cloexec-inotify-init1 inotify_init1() should include IN_CLOEXEC in its type argument to avoid the file descriptor leakage. Without this flag, an opened sensitive file would remain open across a fork+exec to a lower-privileged SELinux domain. Examples: inotify_init1(IN_NONBLOCK); // becomes inotify_init1(IN_NONBLOCK | IN_CLOEXEC); android-cloexec-memfd-create memfd_create() should include MFD_CLOEXEC in its type argument to avoid the file descriptor leakage. Without this flag, an opened sensitive file would remain open across a fork+exec to a lower-privileged SELinux domain. Examples: memfd_create(name, MFD_ALLOW_SEALING); // becomes memfd_create(name, MFD_ALLOW_SEALING | MFD_CLOEXEC); android-cloexec-open A common source of security bugs is code that opens a file without us- ing the O_CLOEXEC flag. Without that flag, an opened sensitive file would remain open across a fork+exec to a lower-privileged SELinux do- main, leaking that sensitive data. Open-like functions including open(), openat(), and open64() should include O_CLOEXEC in their flags argument. Examples: open("filename", O_RDWR); open64("filename", O_RDWR); openat(0, "filename", O_RDWR); // becomes open("filename", O_RDWR | O_CLOEXEC); open64("filename", O_RDWR | O_CLOEXEC); openat(0, "filename", O_RDWR | O_CLOEXEC); android-cloexec-pipe This check detects usage of pipe(). Using pipe() is not recommended, pipe2() is the suggested replacement. The check also adds the O_CLOEXEC flag that marks the file descriptor to be closed in child processes. Without this flag a sensitive file descriptor can be leaked to a child process, potentially into a lower-privileged SELinux domain. Examples: pipe(pipefd); Suggested replacement: pipe2(pipefd, O_CLOEXEC); android-cloexec-pipe2 This check ensures that pipe2() is called with the O_CLOEXEC flag. The check also adds the O_CLOEXEC flag that marks the file descriptor to be closed in child processes. Without this flag a sensitive file descrip- tor can be leaked to a child process, potentially into a lower-privi- leged SELinux domain. Examples: pipe2(pipefd, O_NONBLOCK); Suggested replacement: pipe2(pipefd, O_NONBLOCK | O_CLOEXEC); android-cloexec-socket socket() should include SOCK_CLOEXEC in its type argument to avoid the file descriptor leakage. Without this flag, an opened sensitive file would remain open across a fork+exec to a lower-privileged SELinux do- main. Examples: socket(domain, type, SOCK_STREAM); // becomes socket(domain, type, SOCK_STREAM | SOCK_CLOEXEC); android-comparison-in-temp-failure-retry Diagnoses comparisons that appear to be incorrectly placed in the argu- ment to the TEMP_FAILURE_RETRY macro. Having such a use is incorrect in the vast majority of cases, and will often silently defeat the purpose of the TEMP_FAILURE_RETRY macro. For context, TEMP_FAILURE_RETRY is a convenience macro provided by both glibc and Bionic. Its purpose is to repeatedly run a syscall until it either succeeds, or fails for reasons other than being interrupted. Example buggy usage looks like: char cs[1]; while (TEMP_FAILURE_RETRY(read(STDIN_FILENO, cs, sizeof(cs)) != 0)) { // Do something with cs. } Because TEMP_FAILURE_RETRY will check for whether the result of the comparison is -1, and retry if so. If you encounter this, the fix is simple: lift the comparison out of the TEMP_FAILURE_RETRY argument, like so: char cs[1]; while (TEMP_FAILURE_RETRY(read(STDIN_FILENO, cs, sizeof(cs))) != 0) { // Do something with cs. } Options RetryMacros A comma-separated list of the names of retry macros to be checked. boost-use-to-string This check finds conversion from integer type like int to std::string or std::wstring using boost::lexical_cast, and replace it with calls to std::to_string and std::to_wstring. It doesn't replace conversion from floating points despite the to_string overloads, because it would change the behavior. auto str = boost::lexical_cast<std::string>(42); auto wstr = boost::lexical_cast<std::wstring>(2137LL); // Will be changed to auto str = std::to_string(42); auto wstr = std::to_wstring(2137LL); bugprone-argument-comment Checks that argument comments match parameter names. The check understands argument comments in the form /*parameter_name=*/ that are placed right before the argument. void f(bool foo); ... f(/*bar=*/true); // warning: argument name 'bar' in comment does not match parameter name 'foo' The check tries to detect typos and suggest automated fixes for them. Options StrictMode When false (default value), the check will ignore leading and trailing underscores and case when comparing names -- otherwise they are taken into account. IgnoreSingleArgument When true, the check will ignore the single argument. CommentBoolLiterals When true, the check will add argument comments in the format /*ParameterName=*/ right before the boolean literal argument. Before: void foo(bool TurnKey, bool PressButton); foo(true, false); After: void foo(bool TurnKey, bool PressButton); foo(/*TurnKey=*/true, /*PressButton=*/false); CommentIntegerLiterals When true, the check will add argument comments in the format /*ParameterName=*/ right before the integer literal argument. Before: void foo(int MeaningOfLife); foo(42); After: void foo(int MeaningOfLife); foo(/*MeaningOfLife=*/42); CommentFloatLiterals When true, the check will add argument comments in the format /*ParameterName=*/ right before the float/double literal argu- ment. Before: void foo(float Pi); foo(3.14159); After: void foo(float Pi); foo(/*Pi=*/3.14159); CommentStringLiterals When true, the check will add argument comments in the format /*ParameterName=*/ right before the string literal argument. Before: void foo(const char *String); void foo(const wchar_t *WideString); foo("Hello World"); foo(L"Hello World"); After: void foo(const char *String); void foo(const wchar_t *WideString); foo(/*String=*/"Hello World"); foo(/*WideString=*/L"Hello World"); CommentCharacterLiterals When true, the check will add argument comments in the format /*ParameterName=*/ right before the character literal argument. Before: void foo(char *Character); foo('A'); After: void foo(char *Character); foo(/*Character=*/'A'); CommentUserDefinedLiterals When true, the check will add argument comments in the format /*ParameterName=*/ right before the user defined literal argu- ment. Before: void foo(double Distance); double operator"" _km(long double); foo(402.0_km); After: void foo(double Distance); double operator"" _km(long double); foo(/*Distance=*/402.0_km); CommentNullPtrs When true, the check will add argument comments in the format /*ParameterName=*/ right before the nullptr literal argument. Before: void foo(A* Value); foo(nullptr); After: void foo(A* Value); foo(/*Value=*/nullptr); bugprone-assert-side-effect Finds assert() with side effect. The condition of assert() is evaluated only in debug builds so a condi- tion with side effect can cause different behavior in debug / release builds. Options AssertMacros A comma-separated list of the names of assert macros to be checked. CheckFunctionCalls Whether to treat non-const member and non-member functions as they produce side effects. Disabled by default because it can increase the number of false positive warnings. IgnoredFunctions A semicolon-separated list of the names of functions or methods to be considered as not having side-effects. Regular expressions are accepted, e.g. [Rr]ef(erence)?$ matches every type with suf- fix Ref, ref, Reference and reference. The default is empty. If a name in the list contains the sequence :: it is matched against the qualified typename (i.e. namespace::Type, otherwise it is matched against only the type name (i.e. Type). bugprone-assignment-in-if-condition Finds assignments within conditions of if statements. Such assignments are bug-prone because they may have been intended as equality tests. This check finds all assignments within if conditions, including ones that are not flagged by -Wparentheses due to an extra set of parenthe- ses, and including assignments that call an overloaded operator=(). The identified assignments violate BARR group "Rule 8.2.c". int f = 3; if(f = 4) { // This is identified by both `Wparentheses` and this check - should it have been: `if (f == 4)` ? f = f + 1; } if((f == 5) || (f = 6)) { // the assignment here `(f = 6)` is identified by this check, but not by `-Wparentheses`. Should it have been `(f == 6)` ? f = f + 2; } bugprone-bad-signal-to-kill-thread Finds pthread_kill function calls when a thread is terminated by rais- ing SIGTERM signal and the signal kills the entire process, not just the individual thread. Use any signal except SIGTERM. pthread_kill(thread, SIGTERM); This check corresponds to the CERT C Coding Standard rule POS44-C. Do not use signals to terminate threads. bugprone-bool-pointer-implicit-conversion Checks for conditions based on implicit conversion from a bool pointer to bool. Example: bool *p; if (p) { // Never used in a pointer-specific way. } bugprone-branch-clone Checks for repeated branches in if/else if/else chains, consecutive re- peated branches in switch statements and identical true and false branches in conditional operators. if (test_value(x)) { y++; do_something(x, y); } else { y++; do_something(x, y); } In this simple example (which could arise e.g. as a copy-paste error) the then and else branches are identical and the code is equivalent the following shorter and cleaner code: test_value(x); // can be omitted unless it has side effects y++; do_something(x, y); If this is the intended behavior, then there is no reason to use a con- ditional statement; otherwise the issue can be solved by fixing the branch that is handled incorrectly. The check also detects repeated branches in longer if/else if/else chains where it would be even harder to notice the problem. In switch statements the check only reports repeated branches when they are consecutive, because it is relatively common that the case: labels have some natural ordering and rearranging them would decrease the readability of the code. For example: switch (ch) { case 'a': return 10; case 'A': return 10; case 'b': return 11; case 'B': return 11; default: return 10; } Here the check reports that the 'a' and 'A' branches are identical (and that the 'b' and 'B' branches are also identical), but does not report that the default: branch is also identical to the first two branches. If this is indeed the correct behavior, then it could be implemented as: switch (ch) { case 'a': case 'A': return 10; case 'b': case 'B': return 11; default: return 10; } Here the check does not warn for the repeated return 10;, which is good if we want to preserve that 'a' is before 'b' and default: is the last branch. Switch cases marked with the [[fallthrough]] attribute are ignored. Finally, the check also examines conditional operators and reports code like: return test_value(x) ? x : x; Unlike if statements, the check does not detect chains of conditional operators. Note: This check also reports situations where branches become identi- cal only after preprocessing. bugprone-casting-through-void Detects unsafe or redundant two-step casting operations involving void*. Two-step type conversions via void* are discouraged for several rea- sons. • They obscure code and impede its understandability, complicating maintenance. • These conversions bypass valuable compiler support, erasing warnings related to pointer alignment. It may violate strict aliasing rule and leading to undefined behavior. • In scenarios involving multiple inheritance, ambiguity and unexpected outcomes can arise due to the loss of type information, posing run- time issues. In summary, avoiding two-step type conversions through void* ensures clearer code, maintains essential compiler warnings, and prevents ambi- guity and potential runtime errors, particularly in complex inheritance scenarios. Examples: using IntegerPointer = int *; double *ptr; static_cast<IntegerPointer>(static_cast<void *>(ptr)); // WRONG reinterpret_cast<IntegerPointer>(reinterpret_cast<void *>(ptr)); // WRONG (IntegerPointer)(void *)ptr; // WRONG IntegerPointer(static_cast<void *>(ptr)); // WRONG bugprone-chained-comparison Check detects chained comparison operators that can lead to unintended behavior or logical errors. Chained comparisons are expressions that use multiple comparison opera- tors to compare three or more values. For example, the expression a < b < c compares the values of a, b, and c. However, this expression does not evaluate as (a < b) && (b < c), which is probably what the devel- oper intended. Instead, it evaluates as (a < b) < c, which may produce unintended results, especially when the types of a, b, and c are dif- ferent. To avoid such errors, the check will issue a warning when a chained comparison operator is detected, suggesting to use parentheses to spec- ify the order of evaluation or to use a logical operator to separate comparison expressions. Consider the following examples: int a = 2, b = 6, c = 4; if (a < b < c) { // This block will be executed } In this example, the developer intended to check if a is less than b and b is less than c. However, the expression a < b < c is equivalent to (a < b) < c. Since a < b is true, the expression (a < b) < c is evaluated as 1 < c, which is equivalent to true < c and is invalid in this case as b < c is false. Even that above issue could be detected as comparison of int to bool, there is more dangerous example: bool a = false, b = false, c = true; if (a == b == c) { // This block will be executed } In this example, the developer intended to check if a, b, and c are all equal. However, the expression a == b == c is evaluated as (a == b) == c. Since a == b is true, the expression (a == b) == c is evaluated as true == c, which is equivalent to true == true. This comparison yields true, even though a and b are false, and are not equal to c. To avoid this issue, the developer can use a logical operator to sepa- rate the comparison expressions, like this: if (a == b && b == c) { // This block will not be executed } Alternatively, use of parentheses in the comparison expressions can make the developer's intention more explicit and help avoid misunder- standing. if ((a == b) == c) { // This block will be executed } bugprone-compare-pointer-to-member-virtual-function Detects unspecified behavior about equality comparison between pointer to member virtual function and anything other than null-pointer-con- stant. struct A { void f1(); void f2(); virtual void f3(); virtual void f4(); void g1(int); }; void fn() { bool r1 = (&A::f1 == &A::f2); // ok bool r2 = (&A::f1 == &A::f3); // bugprone bool r3 = (&A::f1 != &A::f3); // bugprone bool r4 = (&A::f3 == nullptr); // ok bool r5 = (&A::f3 == &A::f4); // bugprone void (A::*v1)() = &A::f3; bool r6 = (v1 == &A::f1); // bugprone bool r6 = (v1 == nullptr); // ok void (A::*v2)() = &A::f2; bool r7 = (v2 == &A::f1); // false positive, but potential risk if assigning other value to v2. void (A::*v3)(int) = &A::g1; bool r8 = (v3 == &A::g1); // ok, no virtual function match void(A::*)(int) signature. } Provide warnings on equality comparisons involve pointers to member virtual function or variables which is potential pointer to member vir- tual function and any entity other than a null-pointer constant. In certain compilers, virtual function addresses are not conventional pointers but instead consist of offsets and indexes within a virtual function table (vtable). Consequently, these pointers may vary between base and derived classes, leading to unpredictable behavior when com- pared directly. This issue becomes particularly challenging when deal- ing with pointers to pure virtual functions, as they may not even have a valid address, further complicating comparisons. Instead, it is recommended to utilize the typeid operator or other ap- propriate mechanisms for comparing objects to ensure robust and pre- dictable behavior in your codebase. By heeding this detection and adopting a more reliable comparison method, you can mitigate potential issues related to unspecified behavior, especially when dealing with pointers to member virtual functions or pure virtual functions, thereby improving the overall stability and maintainability of your code. In scenarios involving pointers to member virtual functions, it's only ad- visable to employ nullptr for comparisons. Limitations Does not analyze values stored in a variable. For variable, only ana- lyze all virtual methods in the same class or struct and diagnose when assigning a pointer to member virtual function to this variable is pos- sible. bugprone-copy-constructor-init Finds copy constructors where the constructor doesn't call the copy constructor of the base class. class Copyable { public: Copyable() = default; Copyable(const Copyable &) = default; int memberToBeCopied = 0; }; class X2 : public Copyable { X2(const X2 &other) {} // Copyable(other) is missing }; Also finds copy constructors where the constructor of the base class don't have parameter. class X3 : public Copyable { X3(const X3 &other) : Copyable() {} // other is missing }; Failure to properly initialize base class sub-objects during copy con- struction can result in undefined behavior, crashes, data corruption, or other unexpected outcomes. The check ensures that the copy construc- tor of a derived class properly calls the copy constructor of the base class, helping to prevent bugs and improve code quality. Limitations: • It won't generate warnings for empty classes, as there are no class members (including base class sub-objects) to worry about. • It won't generate warnings for base classes that have copy construc- tor private or deleted. • It won't generate warnings for base classes that are initialized us- ing other non-default constructor, as this could be intentional. The check also suggests a fix-its in some cases. bugprone-dangling-handle Detect dangling references in value handles like std::string_view. These dangling references can be a result of constructing handles from temporary values, where the temporary is destroyed soon after the han- dle is created. Examples: string_view View = string(); // View will dangle. string A; View = A + "A"; // still dangle. vector<string_view> V; V.push_back(string()); // V[0] is dangling. V.resize(3, string()); // V[1] and V[2] will also dangle. string_view f() { // All these return values will dangle. return string(); string S; return S; char Array[10]{}; return Array; } Options HandleClasses A semicolon-separated list of class names that should be treated as handles. By default only std::basic_string_view and std::ex- perimental::basic_string_view are considered. bugprone-dynamic-static-initializers Finds instances of static variables that are dynamically initialized in header files. This can pose problems in certain multithreaded contexts. For example, when disabling compiler generated synchronization instructions for sta- tic variables initialized at runtime (e.g. by -fno-threadsafe-statics), even if a particular project takes the necessary precautions to prevent race conditions during initialization by providing their own synchro- nization, header files included from other projects may not. Therefore, such a check is helpful for ensuring that disabling compiler generated synchronization for static variable initialization will not cause prob- lems. Consider the following code: int foo() { static int k = bar(); return k; } When synchronization of static initialization is disabled, if two threads both call foo for the first time, there is the possibility that k will be double initialized, creating a race condition. bugprone-easily-swappable-parameters Finds function definitions where parameters of convertible types follow each other directly, making call sites prone to calling the function with swapped (or badly ordered) arguments. void drawPoint(int X, int Y) { /* ... */ } FILE *open(const char *Dir, const char *Name, Flags Mode) { /* ... */ } A potential call like drawPoint(-2, 5) or openPath("a.txt", "tmp", Read) is perfectly legal from the language's perspective, but might not be what the developer of the function intended. More elaborate and type-safe constructs, such as opaque typedefs or strong types should be used instead, to prevent a mistaken order of ar- guments. struct Coord2D { int X; int Y; }; void drawPoint(const Coord2D Pos) { /* ... */ } FILE *open(const Path &Dir, const Filename &Name, Flags Mode) { /* ... */ } Due to the potentially elaborate refactoring and API-breaking that is necessary to strengthen the type safety of a project, no automatic fix-its are offered. Options Extension/relaxation options Relaxation (or extension) options can be used to broaden the scope of the analysis and fine-tune the enabling of more mixes between types. Some mixes may depend on coding style or preference specific to a project, however, it should be noted that enabling all of these relax- ations model the way of mixing at call sites the most. These options are expected to make the check report for more functions, and report longer mixable ranges. QualifiersMix Whether to consider parameters of some cvr-qualified T and a differently cvr-qualified T (i.e. T and const T, const T and volatile T, etc.) mixable between one another. If false, the check will consider differently qualified types unmixable. True turns the warnings on. Defaults to false. The following example produces a diagnostic only if Quali- fiersMix is enabled: void *memcpy(const void *Destination, void *Source, std::size_t N) { /* ... */ } ModelImplicitConversions Whether to consider parameters of type T and U mixable if there exists an implicit conversion from T to U and U to T. If false, the check will not consider implicitly convertible types for mixability. True turns warnings for implicit conversions on. Defaults to true. The following examples produce a diagnostic only if ModelImplic- itConversions is enabled: void fun(int Int, double Double) { /* ... */ } void compare(const char *CharBuf, std::string String) { /* ... */ } NOTE: Changing the qualifiers of an expression's type (e.g. from int to const int) is defined as an implicit conversion in the C++ Standard. However, the check separates this deci- sion-making on the mixability of differently qualified types based on whether QualifiersMix was enabled. For example, the following code snippet will only produce a diagnostic if both QualifiersMix and ModelImplicitConversions are enabled: void fun2(int Int, const double Double) { /* ... */ } Filtering options Filtering options can be used to lessen the size of the diagnostics emitted by the checker, whether the aim is to ignore certain constructs or dampen the noisiness. MinimumLength The minimum length required from an adjacent parameter sequence to be diagnosed. Defaults to 2. Might be any positive integer greater or equal to 2. If 0 or 1 is given, the default value 2 will be used instead. For example, if 3 is specified, the examples above will not be matched. IgnoredParameterNames The list of parameter names that should never be considered part of a swappable adjacent parameter sequence. The value is a ;-separated list of names. To ignore unnamed parameters, add "" to the list verbatim (not the empty string, but the two quotes, potentially escaped!). This option is case-sensitive! By default, the following parameter names, and their Upper- case-initial variants are ignored: "" (unnamed parameters), it- erator, begin, end, first, last, lhs, rhs. IgnoredParameterTypeSuffixes The list of parameter type name suffixes that should never be considered part of a swappable adjacent parameter sequence. Pa- rameters which type, as written in the source code, end with an element of this option will be ignored. The value is a ;-sepa- rated list of names. This option is case-sensitive! By default, the following, and their lowercase-initial variants are ignored: bool, It, Iterator, InputIt, ForwardIt, BidirIt, RandomIt, random_iterator, ReverseIt, reverse_iterator, re- verse_const_iterator, RandomIt, random_iterator, ReverseIt, re- verse_iterator, reverse_const_iterator, Const_Iterator, ConstIt- erator, const_reverse_iterator, ConstReverseIterator. In addi- tion, _Bool (but not _bool) is also part of the default value. SuppressParametersUsedTogether Suppresses diagnostics about parameters that are used together or in a similar fashion inside the function's body. Defaults to true. Specifying false will turn off the heuristics. Currently, the following heuristics are implemented which will suppress the warning about the parameter pair involved: • The parameters are used in the same expression, e.g. f(a, b) or a < b. • The parameters are further passed to the same function to the same parameter of that function, of the same overload. E.g. f(a, 1) and f(b, 2) to some f(T, int). NOTE: The check does not perform path-sensitive analysis, and as such, "same function" in this context means the same func- tion declaration. If the same member function of a type on two distinct instances are called with the parameters, it will still be regarded as "same function". • The same member field is accessed, or member method is called of the two parameters, e.g. a.foo() and b.foo(). • Separate return statements return either of the parameters on different code paths. NamePrefixSuffixSilenceDissimilarityTreshold The number of characters two parameter names might be different on either the head or the tail end with the rest of the name the same so that the warning about the two parameters are silenced. Defaults to 1. Might be any positive integer. If 0, the fil- tering heuristic based on the parameters' names is turned off. This option can be used to silence warnings about parameters where the naming scheme indicates that the order of those para- meters do not matter. For example, the parameters LHS and RHS are 1-dissimilar suf- fixes of each other: L and R is the different character, while HS is the common suffix. Similarly, parameters text1, text2, text3 are 1-dissimilar prefixes of each other, with the numbers at the end being the dissimilar part. If the value is at least 1, such cases will not be reported. Limitations This check is designed to check function signatures! The check does not investigate functions that are generated by the com- piler in a context that is only determined from a call site. These cases include variadic functions, functions in C code that do not have an argument list, and C++ template instantiations. Most of these cases, which are otherwise swappable from a caller's standpoint, have no way of getting "fixed" at the definition point. In the case of C++ templates, only primary template definitions and explicit specializa- tions are matched and analyzed. None of the following cases produce a diagnostic: int printf(const char *Format, ...) { /* ... */ } int someOldCFunction() { /* ... */ } template <typename T, typename U> int add(T X, U Y) { return X + Y }; void theseAreNotWarnedAbout() { printf("%d %d\n", 1, 2); // Two ints passed, they could be swapped. someOldCFunction(1, 2, 3); // Similarly, multiple ints passed. add(1, 2); // Instantiates 'add<int, int>', but that's not a user-defined function. } Due to the limitation above, parameters which type are further depen- dent upon template instantiations to prove that they mix with another parameter's is not diagnosed. template <typename T> struct Vector { typedef T element_type; }; // Diagnosed: Explicit instantiation was done by the user, we can prove it // is the same type. void instantiated(int A, Vector<int>::element_type B) { /* ... */ } // Diagnosed: The two parameter types are exactly the same. template <typename T> void exact(typename Vector<T>::element_type A, typename Vector<T>::element_type B) { /* ... */ } // Skipped: The two parameters are both 'T' but we cannot prove this // without actually instantiating. template <typename T> void falseNegative(T A, typename Vector<T>::element_type B) { /* ... */ } In the context of implicit conversions (when ModelImplicitConversions is enabled), the modelling performed by the check warns if the parame- ters are swappable and the swapped order matches implicit conversions. It does not model whether there exists an unrelated third type from which both parameters can be given in a function call. This means that in the following example, even while strs() clearly carries the possi- bility to be called with swapped arguments (as long as the arguments are string literals), will not be warned about. struct String { String(const char *Buf); }; struct StringView { StringView(const char *Buf); operator const char *() const; }; // Skipped: Directly swapping expressions of the two type cannot mix. // (Note: StringView -> const char * -> String would be **two** // user-defined conversions, which is disallowed by the language.) void strs(String Str, StringView SV) { /* ... */ } // Diagnosed: StringView implicitly converts to and from a buffer. void cStr(StringView SV, const char *Buf() { /* ... */ } bugprone-empty-catch Detects and suggests addressing issues with empty catch statements. try { // Some code that can throw an exception } catch(const std::exception&) { } Having empty catch statements in a codebase can be a serious problem that developers should be aware of. Catch statements are used to handle exceptions that are thrown during program execution. When an exception is thrown, the program jumps to the nearest catch statement that matches the type of the exception. Empty catch statements, also known as "swallowing" exceptions, catch the exception but do nothing with it. This means that the exception is not handled properly, and the program continues to run as if nothing happened. This can lead to several issues, such as: • Hidden Bugs: If an exception is caught and ignored, it can lead to hidden bugs that are difficult to diagnose and fix. The root cause of the problem may not be apparent, and the program may continue to be- have in unexpected ways. • Security Issues: Ignoring exceptions can lead to security issues, such as buffer overflows or null pointer dereferences. Hackers can exploit these vulnerabilities to gain access to sensitive data or ex- ecute malicious code. • Poor Code Quality: Empty catch statements can indicate poor code quality and a lack of attention to detail. This can make the codebase difficult to maintain and update, leading to longer development cy- cles and increased costs. • Unreliable Code: Code that ignores exceptions is often unreliable and can lead to unpredictable behavior. This can cause frustration for users and erode trust in the software. To avoid these issues, developers should always handle exceptions prop- erly. This means either fixing the underlying issue that caused the exception or propagating the exception up the call stack to a higher-level handler. If an exception is not important, it should still be logged or reported in some way so that it can be tracked and addressed later. If the exception is something that can be handled locally, then it should be handled within the catch block. This could involve logging the exception or taking other appropriate action to ensure that the ex- ception is not ignored. Here is an example: try { // Some code that can throw an exception } catch (const std::exception& ex) { // Properly handle the exception, e.g.: std::cerr << "Exception caught: " << ex.what() << std::endl; } If the exception cannot be handled locally and needs to be propagated up the call stack, it should be re-thrown or new exception should be thrown. Here is an example: try { // Some code that can throw an exception } catch (const std::exception& ex) { // Re-throw the exception throw; } In some cases, catching the exception at this level may not be neces- sary, and it may be appropriate to let the exception propagate up the call stack. This can be done simply by not using try/catch block. Here is an example: void function() { // Some code that can throw an exception } void callerFunction() { try { function(); } catch (const std::exception& ex) { // Handling exception on higher level std::cerr << "Exception caught: " << ex.what() << std::endl; } } Other potential solution to avoid empty catch statements is to modify the code to avoid throwing the exception in the first place. This can be achieved by using a different API, checking for error conditions be- forehand, or handling errors in a different way that does not involve exceptions. By eliminating the need for try-catch blocks, the code be- comes simpler and less error-prone. Here is an example: // Old code: try { mapContainer["Key"].callFunction(); } catch(const std::out_of_range&) { } // New code if (auto it = mapContainer.find("Key"); it != mapContainer.end()) { it->second.callFunction(); } In conclusion, empty catch statements are a bad practice that can lead to hidden bugs, security issues, poor code quality, and unreliable code. By handling exceptions properly, developers can ensure that their code is robust, secure, and maintainable. Options IgnoreCatchWithKeywords This option can be used to ignore specific catch statements con- taining certain keywords. If a catch statement body contains (case-insensitive) any of the keywords listed in this semi- colon-separated option, then the catch will be ignored, and no warning will be raised. Default value: @TODO;@FIXME. AllowEmptyCatchForExceptions This option can be used to ignore empty catch statements for specific exception types. By default, the check will raise a warning if an empty catch statement is detected, regardless of the type of exception being caught. However, in certain situa- tions, such as when a developer wants to intentionally ignore certain exceptions or handle them in a different way, it may be desirable to allow empty catch statements for specific exception types. To configure this option, a semicolon-separated list of exception type names should be provided. If an exception type name in the list is caught in an empty catch statement, no warn- ing will be raised. Default value: empty string. bugprone-exception-escape Finds functions which may throw an exception directly or indirectly, but they should not. The functions which should not throw exceptions are the following: • Destructors • Move constructors • Move assignment operators • The main() functions • swap() functions • iter_swap() functions • iter_move() functions • Functions marked with throw() or noexcept • Other functions given as option A destructor throwing an exception may result in undefined behavior, resource leaks or unexpected termination of the program. Throwing move constructor or move assignment also may result in undefined behavior or resource leak. The swap() operations expected to be non throwing most of the cases and they are always possible to implement in a non throw- ing way. Non throwing swap() operations are also used to create move operations. A throwing main() function also results in unexpected ter- mination. Functions declared explicitly with noexcept(false) or throw(exception) will be excluded from the analysis, as even though it is not recom- mended for functions like swap(), main(), move constructors, move as- signment operators and destructors, it is a clear indication of the de- veloper's intention and should be respected. WARNING! This check may be expensive on large source files. Options FunctionsThatShouldNotThrow Comma separated list containing function names which should not throw. An example value for this parameter can be WinMain which adds function WinMain() in the Windows API to the list of the functions which should not throw. Default value is an empty string. IgnoredExceptions Comma separated list containing type names which are not counted as thrown exceptions in the check. Default value is an empty string. bugprone-fold-init-type The check flags type mismatches in folds like std::accumulate that might result in loss of precision. std::accumulate folds an input range into an initial value using the type of the latter, with opera- tor+ by default. This can cause loss of precision through: • Truncation: The following code uses a floating point range and an int initial value, so truncation will happen at every application of op- erator+ and the result will be 0, which might not be what the user expected. auto a = {0.5f, 0.5f, 0.5f, 0.5f}; return std::accumulate(std::begin(a), std::end(a), 0); • Overflow: The following code also returns 0. auto a = {65536LL * 65536 * 65536}; return std::accumulate(std::begin(a), std::end(a), 0); bugprone-forward-declaration-namespace Checks if an unused forward declaration is in a wrong namespace. The check inspects all unused forward declarations and checks if there is any declaration/definition with the same name existing, which could indicate that the forward declaration is in a potentially wrong name- space. namespace na { struct A; } namespace nb { struct A {}; } nb::A a; // warning : no definition found for 'A', but a definition with the same name // 'A' found in another namespace 'nb::' This check can only generate warnings, but it can't suggest a fix at this point. bugprone-forwarding-reference-overload The check looks for perfect forwarding constructors that can hide copy or move constructors. If a non const lvalue reference is passed to the constructor, the forwarding reference parameter will be a better match than the const reference parameter of the copy constructor, so the per- fect forwarding constructor will be called, which can be confusing. For detailed description of this issue see: Scott Meyers, Effective Modern C++, Item 26. Consider the following example: class Person { public: // C1: perfect forwarding ctor template<typename T> explicit Person(T&& n) {} // C2: perfect forwarding ctor with parameter default value template<typename T> explicit Person(T&& n, int x = 1) {} // C3: perfect forwarding ctor guarded with enable_if template<typename T, typename X = enable_if_t<is_special<T>, void>> explicit Person(T&& n) {} // C4: variadic perfect forwarding ctor guarded with enable_if template<typename... A, enable_if_t<is_constructible_v<tuple<string, int>, A&&...>, int> = 0> explicit Person(A&&... a) {} // C5: perfect forwarding ctor guarded with requires expression template<typename T> requires requires { is_special<T>; } explicit Person(T&& n) {} // C6: perfect forwarding ctor guarded with concept requirement template<Special T> explicit Person(T&& n) {} // (possibly compiler generated) copy ctor Person(const Person& rhs); }; The check warns for constructors C1 and C2, because those can hide copy and move constructors. We suppress warnings if the copy and the move constructors are both disabled (deleted or private), because there is nothing the perfect forwarding constructor could hide in this case. We also suppress warnings for constructors like C3-C6 that are guarded with an enable_if or a concept, assuming the programmer was aware of the possible hiding. Background For deciding whether a constructor is guarded with enable_if, we con- sider the types of the constructor parameters, the default values of template type parameters and the types of non-type template parameters with a default literal value. If any part of these types is std::en- able_if or std::enable_if_t, we assume the constructor is guarded. bugprone-implicit-widening-of-multiplication-result The check diagnoses instances where a result of a multiplication is im- plicitly widened, and suggests (with fix-it) to either silence the code by making widening explicit, or to perform the multiplication in a wider type, to avoid the widening afterwards. This is mainly useful when operating on very large buffers. For exam- ple, consider: void zeroinit(char* base, unsigned width, unsigned height) { for(unsigned row = 0; row != height; ++row) { for(unsigned col = 0; col != width; ++col) { char* ptr = base + row * width + col; *ptr = 0; } } } This is fine in general, but if width * height overflows, you end up wrapping back to the beginning of base instead of processing the entire requested buffer. Indeed, this only matters for pretty large buffers (4GB+), but that can happen very easily for example in image processing, where for that to happen you "only" need a ~269MPix image. Options UseCXXStaticCastsInCppSources When suggesting fix-its for C++ code, should C++-style sta- tic_cast<>()'s be suggested, or C-style casts. Defaults to true. UseCXXHeadersInCppSources When suggesting to include the appropriate header in C++ code, should <cstddef> header be suggested, or <stddef.h>. Defaults to true. Examples: long mul(int a, int b) { return a * b; // warning: performing an implicit widening conversion to type 'long' of a multiplication performed in type 'int' } char* ptr_add(char *base, int a, int b) { return base + a * b; // warning: result of multiplication in type 'int' is used as a pointer offset after an implicit widening conversion to type 'ssize_t' } char ptr_subscript(char *base, int a, int b) { return base[a * b]; // warning: result of multiplication in type 'int' is used as a pointer offset after an implicit widening conversion to type 'ssize_t' } bugprone-inaccurate-erase Checks for inaccurate use of the erase() method. Algorithms like remove() do not actually remove any element from the container but return an iterator to the first redundant element at the end of the container. These redundant elements must be removed using the erase() method. This check warns when not all of the elements will be removed due to using an inappropriate overload. For example, the following code erases only one element: std::vector<int> xs; ... xs.erase(std::remove(xs.begin(), xs.end(), 10)); Call the two-argument overload of erase() to remove the subrange: std::vector<int> xs; ... xs.erase(std::remove(xs.begin(), xs.end(), 10), xs.end()); bugprone-inc-dec-in-conditions Detects when a variable is both incremented/decremented and referenced inside a complex condition and suggests moving them outside to avoid ambiguity in the variable's value. When a variable is modified and also used in a complex condition, it can lead to unexpected behavior. The side-effect of changing the vari- able's value within the condition can make the code difficult to reason about. Additionally, the developer's intended timing for the modifica- tion of the variable may not be clear, leading to misunderstandings and errors. This can be particularly problematic when the condition in- volves logical operators like && and ||, where the order of evaluation can further complicate the situation. Consider the following example: int i = 0; // ... if (i++ < 5 && i > 0) { // do something } In this example, the result of the expression may not be what the de- veloper intended. The original intention of the developer could be to increment i after the entire condition is evaluated, but in reality, i will be incremented before i > 0 is executed. This can lead to unex- pected behavior and bugs in the code. To fix this issue, the developer should separate the increment operation from the condition and perform it separately. For example, they can increment i in a separate state- ment before or after the condition is evaluated. This ensures that the value of i is predictable and consistent throughout the code. int i = 0; // ... i++; if (i <= 5 && i > 0) { // do something } Another common issue occurs when multiple increments or decrements are performed on the same variable inside a complex condition. For example: int i = 4; // ... if (i++ < 5 || --i > 2) { // do something } There is a potential issue with this code due to the order of evalua- tion in C++. The || operator used in the condition statement guaran- tees that if the first operand evaluates to true, the second operand will not be evaluated. This means that if i were initially 4, the first operand i < 5 would evaluate to true and the second operand i > 2 would not be evaluated. As a result, the decrement operation --i would not be executed and i would hold value 5, which may not be the intended be- havior for the developer. To avoid this potential issue, the both increment and decrement opera- tion on i should be moved outside the condition statement. bugprone-incorrect-enable-if Detects incorrect usages of std::enable_if that don't name the nested type type. In C++11 introduced std::enable_if as a convenient way to leverage SFI- NAE. One form of using std::enable_if is to declare an unnamed tem- plate type parameter with a default type equal to typename std::en- able_if<condition>::type. If the author forgets to name the nested type type, then the code will always consider the candidate template even if the condition is not met. Below are some examples of code using std::enable_if correctly and in- correct examples that this check flags. template <typename T, typename = typename std::enable_if<T::some_trait>::type> void valid_usage() { ... } template <typename T, typename = std::enable_if_t<T::some_trait>> void valid_usage_with_trait_helpers() { ... } // The below code is not a correct application of SFINAE. Even if // T::some_trait is not true, the function will still be considered in the // set of function candidates. It can either incorrectly select the function // when it should not be a candidates, and/or lead to hard compile errors // if the body of the template does not compile if the condition is not // satisfied. template <typename T, typename = std::enable_if<T::some_trait>> void invalid_usage() { ... } // The tool suggests the following replacement for 'invalid_usage': template <typename T, typename = typename std::enable_if<T::some_trait>::type> void fixed_invalid_usage() { ... } C++14 introduced the trait helper std::enable_if_t which reduces the likelihood of this error. C++20 introduces constraints, which generally supersede the use of std::enable_if. See modernize-type-traits for an- other tool that will replace std::enable_if with std::enable_if_t, and see modernize-use-constraints for another tool that replaces std::en- able_if with C++20 constraints. Consider these newer mechanisms where possible. bugprone-incorrect-roundings Checks the usage of patterns known to produce incorrect rounding. Pro- grammers often use: (int)(double_expression + 0.5) to round the double expression to an integer. The problem with this: 1. It is unnecessarily slow. 2. It is incorrect. The number 0.499999975 (smallest representable float number below 0.5) rounds to 1.0. Even worse behavior for nega- tive numbers where both -0.5f and -1.4f both round to 0.0. bugprone-infinite-loop Finds obvious infinite loops (loops where the condition variable is not changed at all). Finding infinite loops is well-known to be impossible (halting prob- lem). However, it is possible to detect some obvious infinite loops, for example, if the loop condition is not changed. This check detects such loops. A loop is considered infinite if it does not have any loop exit statement (break, continue, goto, return, throw or a call to a function called as [[noreturn]]) and all of the following conditions hold for every variable in the condition: • It is a local variable. • It has no reference or pointer aliases. • It is not a structure or class member. Furthermore, the condition must not contain a function call to consider the loop infinite since functions may return different values for dif- ferent calls. For example, the following loop is considered infinite i is not changed in the body: int i = 0, j = 0; while (i < 10) { ++j; } bugprone-integer-division Finds cases where integer division in a floating point context is likely to cause unintended loss of precision. No reports are made if divisions are part of the following expressions: • operands of operators expecting integral or bool types, • call expressions of integral or bool types, and • explicit cast expressions to integral or bool types, as these are interpreted as signs of deliberateness from the program- mer. Examples: float floatFunc(float); int intFunc(int); double d; int i = 42; // Warn, floating-point values expected. d = 32 * 8 / (2 + i); d = 8 * floatFunc(1 + 7 / 2); d = i / (1 << 4); // OK, no integer division. d = 32 * 8.0 / (2 + i); d = 8 * floatFunc(1 + 7.0 / 2); d = (double)i / (1 << 4); // OK, there are signs of deliberateness. d = 1 << (i / 2); d = 9 + intFunc(6 * i / 32); d = (int)(i / 32) - 8; bugprone-lambda-function-name Checks for attempts to get the name of a function from within a lambda expression. The name of a lambda is always something like operator(), which is almost never what was intended. Example: void FancyFunction() { [] { printf("Called from %s\n", __func__); }(); [] { printf("Now called from %s\n", __FUNCTION__); }(); } Output: Called from operator() Now called from operator() Likely intended output: Called from FancyFunction Now called from FancyFunction Options IgnoreMacros The value true specifies that attempting to get the name of a function from within a macro should not be diagnosed. The de- fault value is false. bugprone-macro-parentheses Finds macros that can have unexpected behavior due to missing parenthe- ses. Macros are expanded by the preprocessor as-is. As a result, there can be unexpected behavior; operators may be evaluated in unexpected order and unary operators may become binary operators, etc. When the replacement list has an expression, it is recommended to sur- round it with parentheses. This ensures that the macro result is evalu- ated completely before it is used. It is also recommended to surround macro arguments in the replacement list with parentheses. This ensures that the argument value is calcu- lated properly. bugprone-macro-repeated-side-effects Checks for repeated argument with side effects in macros. bugprone-misplaced-operator-in-strlen-in-alloc Finds cases where 1 is added to the string in the argument to strlen(), strnlen(), strnlen_s(), wcslen(), wcsnlen(), and wcsnlen_s() instead of the result and the value is used as an argument to a memory allocation function (malloc(), calloc(), realloc(), alloca()) or the new[] opera- tor in C++. The check detects error cases even if one of these func- tions (except the new[] operator) is called by a constant function pointer. Cases where 1 is added both to the parameter and the result of the strlen()-like function are ignored, as are cases where the whole addition is surrounded by extra parentheses. C example code: void bad_malloc(char *str) { char *c = (char*) malloc(strlen(str + 1)); } The suggested fix is to add 1 to the return value of strlen() and not to its argument. In the example above the fix would be char *c = (char*) malloc(strlen(str) + 1); C++ example code: void bad_new(char *str) { char *c = new char[strlen(str + 1)]; } As in the C code with the malloc() function, the suggested fix is to add 1 to the return value of strlen() and not to its argument. In the example above the fix would be char *c = new char[strlen(str) + 1]; Example for silencing the diagnostic: void bad_malloc(char *str) { char *c = (char*) malloc(strlen((str + 1))); } bugprone-misplaced-pointer-arithmetic-in-alloc Finds cases where an integer expression is added to or subtracted from the result of a memory allocation function (malloc(), calloc(), real- loc(), alloca()) instead of its argument. The check detects error cases even if one of these functions is called by a constant function pointer. Example code: void bad_malloc(int n) { char *p = (char*) malloc(n) + 10; } The suggested fix is to add the integer expression to the argument of malloc and not to its result. In the example above the fix would be char *p = (char*) malloc(n + 10); bugprone-misplaced-widening-cast This check will warn when there is a cast of a calculation result to a bigger type. If the intention of the cast is to avoid loss of precision then the cast is misplaced, and there can be loss of precision. Other- wise the cast is ineffective. Example code: long f(int x) { return (long)(x * 1000); } The result x * 1000 is first calculated using int precision. If the re- sult exceeds int precision there is loss of precision. Then the result is casted to long. If there is no loss of precision then the cast can be removed or you can explicitly cast to int instead. If you want to avoid loss of precision then put the cast in a proper location, for instance: long f(int x) { return (long)x * 1000; } Implicit casts Forgetting to place the cast at all is at least as dangerous and at least as common as misplacing it. If CheckImplicitCasts is enabled the check also detects these cases, for instance: long f(int x) { return x * 1000; } Floating point Currently warnings are only written for integer conversion. No warning is written for this code: double f(float x) { return (double)(x * 10.0f); } Options CheckImplicitCasts If true, enables detection of implicit casts. Default is false. bugprone-move-forwarding-reference Warns if std::move is called on a forwarding reference, for example: template <typename T> void foo(T&& t) { bar(std::move(t)); } Forwarding references should typically be passed to std::forward in- stead of std::move, and this is the fix that will be suggested. (A forwarding reference is an rvalue reference of a type that is a de- duced function template argument.) In this example, the suggested fix would be bar(std::forward<T>(t)); Background Code like the example above is sometimes written with the expectation that T&& will always end up being an rvalue reference, no matter what type is deduced for T, and that it is therefore not possible to pass an lvalue to foo(). However, this is not true. Consider this example: std::string s = "Hello, world"; foo(s); This code compiles and, after the call to foo(), s is left in an inde- terminate state because it has been moved from. This may be surprising to the caller of foo() because no std::move was used when calling foo(). The reason for this behavior lies in the special rule for template ar- gument deduction on function templates like foo() -- i.e. on function templates that take an rvalue reference argument of a type that is a deduced function template argument. (See section [temp.deduct.call]/3 in the C++11 standard.) If foo() is called on an lvalue (as in the example above), then T is deduced to be an lvalue reference. In the example, T is deduced to be std::string &. The type of the argument t therefore becomes std::string& &&; by the reference collapsing rules, this collapses to std::string&. This means that the foo(s) call passes s as an lvalue reference, and foo() ends up moving s and thereby placing it into an indeterminate state. bugprone-multi-level-implicit-pointer-conversion Detects implicit conversions between pointers of different levels of indirection. Conversions between pointer types of different levels of indirection can be dangerous and may lead to undefined behavior, particularly if the converted pointer is later cast to a type with a different level of indirection. For example, converting a pointer to a pointer to an int (int**) to a void* can result in the loss of information about the original level of indirection, which can cause problems when attempting to use the converted pointer. If the converted pointer is later cast to a type with a different level of indirection and dereferenced, it may lead to access violations, memory corruption, or other undefined behav- ior. Consider the following example: void foo(void* ptr); int main() { int x = 42; int* ptr = &x; int** ptr_ptr = &ptr; foo(ptr_ptr); // warning will trigger here return 0; } In this example, foo() is called with ptr_ptr as its argument. However, ptr_ptr is a int** pointer, while foo() expects a void* pointer. This results in an implicit pointer level conversion, which could cause is- sues if foo() dereferences the pointer assuming it's a int* pointer. Using an explicit cast is a recommended solution to prevent issues caused by implicit pointer level conversion, as it allows the developer to explicitly state their intention and show their reasoning for the type conversion. Additionally, it is recommended that developers thor- oughly check and verify the safety of the conversion before using an explicit cast. This extra level of caution can help catch potential is- sues early on in the development process, improving the overall relia- bility and maintainability of the code. bugprone-multiple-new-in-one-expression Finds multiple new operator calls in a single expression, where the al- located memory by the first new may leak if the second allocation fails and throws exception. C++ does often not specify the exact order of evaluation of the operands of an operator or arguments of a function. Therefore if a first allocation succeeds and a second fails, in an exception handler it is not possible to tell which allocation has failed and free the memory. Even if the order is fixed the result of a first new may be stored in a temporary location that is not reachable at the time when a second allocation fails. It is best to avoid any expression that con- tains more than one operator new call, if exception handling is used to check for allocation errors. Different rules apply for are the short-circuit operators || and && and the , operator, where evaluation of one side must be completed before the other starts. Expressions of a list-initialization (initialization or construction using { and } characters) are evaluated in fixed order. Similarly, condition of a ? operator is evaluated before the branches are evaluated. The check reports warning if two new calls appear in one expression at different sides of an operator, or if new calls appear in different ar- guments of a function call (that can be an object construction with () syntax). These new calls can be nested at any level. For any warning to be emitted the new calls should be in a code block where exception handling is used with catch for std::bad_alloc or std::exception. At ||, &&, ,, ? (condition and one branch) operators no warning is emit- ted. No warning is emitted if both of the memory allocations are not assigned to a variable or not passed directly to a function. The rea- son is that in this case the memory may be intentionally not freed or the allocated objects can be self-destructing objects. Examples: struct A { int Var; }; struct B { B(); B(A *); int Var; }; struct C { int *X1; int *X2; }; void f(A *, B *); int f1(A *); int f1(B *); bool f2(A *); void foo() { A *PtrA; B *PtrB; try { // Allocation of 'B'/'A' may fail after memory for 'A'/'B' was allocated. f(new A, new B); // warning: memory allocation may leak if an other allocation is sequenced after it and throws an exception; order of these allocations is undefined // List (aggregate) initialization is used. C C1{new int, new int}; // no warning // Allocation of 'B'/'A' may fail after memory for 'A'/'B' was allocated but not yet passed to function 'f1'. int X = f1(new A) + f1(new B); // warning: memory allocation may leak if an other allocation is sequenced after it and throws an exception; order of these allocations is undefined // Allocation of 'B' may fail after memory for 'A' was allocated. // From C++17 on memory for 'B' is allocated first but still may leak if allocation of 'A' fails. PtrB = new B(new A); // warning: memory allocation may leak if an other allocation is sequenced after it and throws an exception // 'new A' and 'new B' may be performed in any order. // 'new B'/'new A' may fail after memory for 'A'/'B' was allocated but not assigned to 'PtrA'/'PtrB'. (PtrA = new A)->Var = (PtrB = new B)->Var; // warning: memory allocation may leak if an other allocation is sequenced after it and throws an exception; order of these allocations is undefined // Evaluation of 'f2(new A)' must be finished before 'f1(new B)' starts. // If 'new B' fails the allocated memory for 'A' is supposedly handled correctly because function 'f2' could take the ownership. bool Z = f2(new A) || f1(new B); // no warning X = (f2(new A) ? f1(new A) : f1(new B)); // no warning // No warning if the result of both allocations is not passed to a function // or stored in a variable. (new A)->Var = (new B)->Var; // no warning // No warning if at least one non-throwing allocation is used. f(new(std::nothrow) A, new B); // no warning } catch(std::bad_alloc) { } // No warning if the allocation is outside a try block (or no catch handler exists for std::bad_alloc). // (The fact if exceptions can escape from 'foo' is not taken into account.) f(new A, new B); // no warning } bugprone-multiple-statement-macro Detect multiple statement macros that are used in unbraced condition- als. Only the first statement of the macro will be inside the condi- tional and the other ones will be executed unconditionally. Example: #define INCREMENT_TWO(x, y) (x)++; (y)++ if (do_increment) INCREMENT_TWO(a, b); // (b)++ will be executed unconditionally. bugprone-narrowing-conversions The bugprone-narrowing-conversions check is an alias, please see cppcoreguidelines-narrowing-conversions for more information. bugprone-no-escape Finds pointers with the noescape attribute that are captured by an asynchronously-executed block. The block arguments in dispatch_async() and dispatch_after() are guaranteed to escape, so it is an error if a pointer with the noescape attribute is captured by one of these blocks. The following is an example of an invalid use of the noescape at- tribute. void foo(__attribute__((noescape)) int *p) { dispatch_async(queue, ^{ *p = 123; }); }); bugprone-non-zero-enum-to-bool-conversion Detect implicit and explicit casts of enum type into bool where enum type doesn't have a zero-value enumerator. If the enum is used only to hold values equal to its enumerators, then conversion to bool will al- ways result in true value. This can lead to unnecessary code that re- duces readability and maintainability and can result in bugs. May produce false positives if the enum is used to store other values (used as a bit-mask or zero-initialized on purpose). To deal with them, // NOLINT or casting first to the underlying type before casting to bool can be used. It is important to note that this check will not generate warnings if the definition of the enumeration type is not available. Additionally, C++11 enumeration classes are supported by this check. Overall, this check serves to improve code quality and readability by identifying and flagging instances where implicit or explicit casts from enumeration types to boolean could cause potential issues. Example enum EStatus { OK = 1, NOT_OK, UNKNOWN }; void process(EStatus status) { if (!status) { // this true-branch won't be executed return; } // proceed with "valid data" } Options EnumIgnoreList Option is used to ignore certain enum types when checking for implicit/explicit casts to bool. It accepts a semicolon-sepa- rated list of (fully qualified) enum type names or regular ex- pressions that match the enum type names. The default value is an empty string, which means no enums will be ignored. bugprone-not-null-terminated-result Finds function calls where it is possible to cause a not null-termi- nated result. Usually the proper length of a string is strlen(src) + 1 or equal length of this expression, because the null terminator needs an extra space. Without the null terminator it can result in undefined behavior when the string is read. The following and their respective wchar_t based functions are checked: memcpy, memcpy_s, memchr, memmove, memmove_s, strerror_s, strncmp, strxfrm The following is a real-world example where the programmer forgot to increase the passed third argument, which is size_t length. That is why the length of the allocated memory is not enough to hold the null ter- minator. static char *stringCpy(const std::string &str) { char *result = reinterpret_cast<char *>(malloc(str.size())); memcpy(result, str.data(), str.size()); return result; } In addition to issuing warnings, fix-it rewrites all the necessary code. It also tries to adjust the capacity of the destination array: static char *stringCpy(const std::string &str) { char *result = reinterpret_cast<char *>(malloc(str.size() + 1)); strcpy(result, str.data()); return result; } Note: It cannot guarantee to rewrite every of the path-sensitive memory allocations. Transformation rules of 'memcpy()' It is possible to rewrite the memcpy() and memcpy_s() calls as the fol- lowing four functions: strcpy(), strncpy(), strcpy_s(), strncpy_s(), where the latter two are the safer versions of the former two. It rewrites the wchar_t based memory handler functions respectively. Rewrite based on the destination array • If copy to the destination array cannot overflow [1] the new function should be the older copy function (ending with cpy), because it is more efficient than the safe version. • If copy to the destination array can overflow [1] and WantToUseSafeFunctions is set to true and it is possible to obtain the capacity of the destination array then the new function could be the safe version (ending with cpy_s). • If the new function is could be safe version and C++ files are ana- lyzed and the destination array is plain char/wchar_t without un/signed then the length of the destination array can be omitted. • If the new function is could be safe version and the destination ar- ray is un/signed it needs to be casted to plain char */wchar_t *. [1] It is possible to overflow: • If the capacity of the destination array is unknown. • If the given length is equal to the destination array's capac- ity. Rewrite based on the length of the source string • If the given length is strlen(source) or equal length of this expres- sion then the new function should be the older copy function (ending with cpy), as it is more efficient than the safe version (ending with cpy_s). • Otherwise we assume that the programmer wanted to copy 'N' charac- ters, so the new function is ncpy-like which copies 'N' characters. Transformations with 'strlen()' or equal length of this expression It transforms the wchar_t based memory and string handler functions re- spectively (where only strerror_s does not have wchar_t based alias). Memory handler functions memcpy Please visit the Transformation rules of 'memcpy()' section. memchr Usually there is a C-style cast and it is needed to be removed, because the new function strchr's return type is correct. The given length is going to be removed. memmove If safe functions are available the new function is memmove_s, which has a new second argument which is the length of the destination array, it is adjusted, and the length of the source string is incre- mented by one. If safe functions are not available the given length is incremented by one. memmove_s The given length is incremented by one. String handler functions strerror_s The given length is incremented by one. strncmp If the third argument is the first or the second argument's length + 1 it has to be truncated without the + 1 operation. strxfrm The given length is incremented by one. Options WantToUseSafeFunctions The value true specifies that the target environment is consid- ered to implement '_s' suffixed memory and string handler func- tions which are safer than older versions (e.g. 'memcpy_s()'). The default value is true. bugprone-optional-value-conversion Detects potentially unintentional and redundant conversions where a value is extracted from an optional-like type and then used to create a new instance of the same optional-like type. These conversions might be the result of developer oversight, leftovers from code refactoring, or other situations that could lead to unin- tended exceptions or cases where the resulting optional is always ini- tialized, which might be unexpected behavior. To illustrate, consider the following problematic code snippet: #include <optional> void print(std::optional<int>); int main() { std::optional<int> opt; // ... // Unintentional conversion from std::optional<int> to int and back to // std::optional<int>: print(opt.value()); // ... } A better approach would be to directly pass opt to the print function without extracting its value: #include <optional> void print(std::optional<int>); int main() { std::optional<int> opt; // ... // Proposed code: Directly pass the std::optional<int> to the print // function. print(opt); // ... } By passing opt directly to the print function, unnecessary conversions are avoided, and potential unintended behavior or exceptions are mini- mized. Value extraction using operator * is matched by default. The support for non-standard optional types such as boost::optional or absl::op- tional may be limited. Options: OptionalTypes Semicolon-separated list of (fully qualified) optional type names or regular expressions that match the optional types. De- fault value is ::std::optional;::absl::optional;::boost::op- tional. ValueMethods Semicolon-separated list of (fully qualified) method names or regular expressions that match the methods. Default value is ::value$;::get$. bugprone-parent-virtual-call Detects and fixes calls to grand-...parent virtual methods instead of calls to overridden parent's virtual methods. struct A { int virtual foo() {...} }; struct B: public A { int foo() override {...} }; struct C: public B { int foo() override { A::foo(); } // ^^^^^^^^ // warning: qualified name A::foo refers to a member overridden in subclass; did you mean 'B'? [bugprone-parent-virtual-call] }; bugprone-posix-return Checks if any calls to pthread_* or posix_* functions (except posix_openpt) expect negative return values. These functions return ei- ther 0 on success or an errno on failure, which is positive only. Example buggy usage looks like: if (posix_fadvise(...) < 0) { This will never happen as the return value is always non-negative. A simple fix could be: if (posix_fadvise(...) > 0) { bugprone-redundant-branch-condition Finds condition variables in nested if statements that were also checked in the outer if statement and were not changed. Simple example: bool onFire = isBurning(); if (onFire) { if (onFire) scream(); } Here onFire is checked both in the outer if and the inner if statement without a possible change between the two checks. The check warns for this code and suggests removal of the second checking of variable on- Fire. The checker also detects redundant condition checks if the condition variable is an operand of a logical "and" (&&) or a logical "or" (||) operator: bool onFire = isBurning(); if (onFire) { if (onFire && peopleInTheBuilding > 0) scream(); } bool onFire = isBurning(); if (onFire) { if (onFire || isCollapsing()) scream(); } In the first case (logical "and") the suggested fix is to remove the redundant condition variable and keep the other side of the &&. In the second case (logical "or") the whole if is removed similarly to the simple case on the top. The condition of the outer if statement may also be a logical "and" (&&) expression: bool onFire = isBurning(); if (onFire && fireFighters < 10) { if (someOtherCondition()) { if (onFire) scream(); } } The error is also detected if both the outer statement is a logical "and" (&&) and the inner statement is a logical "and" (&&) or "or" (||). The inner if statement does not have to be a direct descendant of the outer one. No error is detected if the condition variable may have been changed between the two checks: bool onFire = isBurning(); if (onFire) { tryToExtinguish(onFire); if (onFire && peopleInTheBuilding > 0) scream(); } Every possible change is considered, thus if the condition variable is not a local variable of the function, it is a volatile or it has an alias (pointer or reference) then no warning is issued. Known limitations The else branch is not checked currently for negated condition vari- able: bool onFire = isBurning(); if (onFire) { scream(); } else { if (!onFire) { continueWork(); } } The checker currently only detects redundant checking of single condi- tion variables. More complex expressions are not checked: if (peopleInTheBuilding == 1) { if (peopleInTheBuilding == 1) { doSomething(); } } bugprone-reserved-identifier cert-dcl37-c and cert-dcl51-cpp redirect here as an alias for this check. Checks for usages of identifiers reserved for use by the implementa- tion. The C and C++ standards both reserve the following names for such use: • identifiers that begin with an underscore followed by an uppercase letter; • identifiers in the global namespace that begin with an underscore. The C standard additionally reserves names beginning with a double un- derscore, while the C++ standard strengthens this to reserve names with a double underscore occurring anywhere. Violating the naming rules above results in undefined behavior. namespace NS { void __f(); // name is not allowed in user code using _Int = int; // same with this #define cool__macro // also this } int _g(); // disallowed in global namespace only The check can also be inverted, i.e. it can be configured to flag any identifier that is _not_ a reserved identifier. This mode is for use by e.g. standard library implementors, to ensure they don't infringe on the user namespace. This check does not (yet) check for other reserved names, e.g. macro names identical to language keywords, and names specifically reserved by language standards, e.g. C++ 'zombie names' and C future library di- rections. This check corresponds to CERT C Coding Standard rule DCL37-C. Do not declare or define a reserved identifier as well as its C++ counterpart, DCL51-CPP. Do not declare or define a reserved identifier. Options Invert If true, inverts the check, i.e. flags names that are not re- served. Default is false. AllowedIdentifiers Semicolon-separated list of regular expressions that the check ignores. Default is an empty list. bugprone-shared-ptr-array-mismatch Finds initializations of C++ shared pointers to non-array type that are initialized with an array. If a shared pointer std::shared_ptr<T> is initialized with a new-ex- pression new T[] the memory is not deallocated correctly. The pointer uses plain delete in this case to deallocate the target memory. Instead a delete[] call is needed. A std::shared_ptr<T[]> calls the correct delete operator. The check offers replacement of shared_ptr<T> to shared_ptr<T[]> if it is used at a single variable declaration (one variable in one state- ment). Example: std::shared_ptr<Foo> x(new Foo[10]); // -> std::shared_ptr<Foo[]> x(new Foo[10]); // ^ warning: shared pointer to non-array is initialized with array [bugprone-shared-ptr-array-mismatch] std::shared_ptr<Foo> x1(new Foo), x2(new Foo[10]); // no replacement // ^ warning: shared pointer to non-array is initialized with array [bugprone-shared-ptr-array-mismatch] std::shared_ptr<Foo> x3(new Foo[10], [](const Foo *ptr) { delete[] ptr; }); // no warning struct S { std::shared_ptr<Foo> x(new Foo[10]); // no replacement in this case // ^ warning: shared pointer to non-array is initialized with array [bugprone-shared-ptr-array-mismatch] }; This check partially covers the CERT C++ Coding Standard rule MEM51-CPP. Properly deallocate dynamically allocated resources However, only the std::shared_ptr case is detected by this check. bugprone-signal-handler Finds specific constructs in signal handler functions that can cause undefined behavior. The rules for what is allowed differ between C++ language versions. Checked signal handler rules for C: • Calls to non-asynchronous-safe functions are not allowed. Checked signal handler rules for up to and including C++14: • Calls to non-asynchronous-safe functions are not allowed. • C++-specific code constructs are not allowed in signal handlers. In other words, only the common subset of C and C++ is allowed to be used. • Calls to functions with non-C linkage are not allowed (including the signal handler itself). The check is disabled on C++17 and later. Asynchronous-safety is determined by comparing the function's name against a set of known functions. In addition, the function must come from a system header include and in a global namespace. The (possible) arguments passed to the function are not checked. Any function that cannot be determined to be asynchronous-safe is assumed to be non-asyn- chronous-safe by the check, including user functions for which only the declaration is visible. Calls to user-defined functions with visible definitions are checked recursively. This check implements the CERT C Coding Standard rule SIG30-C. Call only asynchronous-safe functions within signal handlers and the rule MSC54-CPP. A signal handler must be a plain old function. It has the alias names cert-sig30-c and cert-msc54-cpp. Options AsyncSafeFunctionSet Selects which set of functions is considered as asynchro- nous-safe (and therefore allowed in signal handlers). It can be set to the following values: minimal Selects a minimal set that is defined in the CERT SIG30-C rule. and includes functions abort(), _Exit(), quick_exit() and signal(). POSIX Selects a larger set of functions that is listed in POSIX.1-2017 (see this link for more information). The following functions are included: _Exit, _exit, abort, accept, access, aio_error, aio_return, aio_suspend, alarm, bind, cfgetispeed, cfgetospeed, cfsetispeed, cfse- tospeed, chdir, chmod, chown, clock_gettime, close, con- nect, creat, dup, dup2, execl, execle, execv, execve, faccessat, fchdir, fchmod, fchmodat, fchown, fchownat, fcntl, fdatasync, fexecve, ffs, fork, fstat, fstatat, fsync, ftruncate, futimens, getegid, geteuid, getgid, getgroups, getpeername, getpgrp, getpid, getppid, get- sockname, getsockopt, getuid, htonl, htons, kill, link, linkat, listen, longjmp, lseek, lstat, memccpy, memchr, memcmp, memcpy, memmove, memset, mkdir, mkdirat, mkfifo, mkfifoat, mknod, mknodat, ntohl, ntohs, open, openat, pause, pipe, poll, posix_trace_event, pselect, pthread_kill, pthread_self, pthread_sigmask, quick_exit, raise, read, readlink, readlinkat, recv, recvfrom, recvmsg, rename, renameat, rmdir, select, sem_post, send, sendmsg, sendto, setgid, setpgid, setsid, setsockopt, se- tuid, shutdown, sigaction, sigaddset, sigdelset, sigemp- tyset, sigfillset, sigismember, siglongjmp, signal, sig- pause, sigpending, sigprocmask, sigqueue, sigset, sigsus- pend, sleep, sockatmark, socket, socketpair, stat, stpcpy, stpncpy, strcat, strchr, strcmp, strcpy, strcspn, strlen, strncat, strncmp, strncpy, strnlen, strpbrk, str- rchr, strspn, strstr, strtok_r, symlink, symlinkat, tcdrain, tcflow, tcflush, tcgetattr, tcgetpgrp, tcsend- break, tcsetattr, tcsetpgrp, time, timer_getoverrun, timer_gettime, timer_settime, times, umask, uname, un- link, unlinkat, utime, utimensat, utimes, wait, waitpid, wcpcpy, wcpncpy, wcscat, wcschr, wcscmp, wcscpy, wcscspn, wcslen, wcsncat, wcsncmp, wcsncpy, wcsnlen, wcspbrk, wc- srchr, wcsspn, wcsstr, wcstok, wmemchr, wmemcmp, wmemcpy, wmemmove, wmemset, write The function quick_exit is not included in the POSIX list but it is included here in the set of safe functions. The default value is POSIX. bugprone-signed-char-misuse cert-str34-c redirects here as an alias for this check. For the CERT alias, the DiagnoseSignedUnsignedCharComparisons option is set to false. Finds those signed char -> integer conversions which might indicate a programming error. The basic problem with the signed char, that it might store the non-ASCII characters as negative values. This behavior can cause a misunderstanding of the written code both when an explicit and when an implicit conversion happens. When the code contains an explicit signed char -> integer conversion, the human programmer probably expects that the converted value matches with the character code (a value from [0..255]), however, the actual value is in [-128..127] interval. To avoid this kind of misinterpreta- tion, the desired way of converting from a signed char to an integer value is converting to unsigned char first, which stores all the char- acters in the positive [0..255] interval which matches the known char- acter codes. In case of implicit conversion, the programmer might not actually be aware that a conversion happened and char value is used as an integer. There are some use cases when this unawareness might lead to a func- tionally imperfect code. For example, checking the equality of a signed char and an unsigned char variable is something we should avoid in C++ code. During this comparison, the two variables are converted to integers which have different value ranges. For signed char, the non-ASCII characters are stored as a value in [-128..-1] interval, while the same characters are stored in the [128..255] interval for an unsigned char. It depends on the actual platform whether plain char is handled as signed char by default and so it is caught by this check or not. To change the default behavior you can use -funsigned-char and -fsigned-char compilation options. Currently, this check warns in the following cases: - signed char is assigned to an integer variable - signed char and unsigned char are compared with equality/inequality operator - signed char is converted to an integer in the array subscript See also: STR34-C. Cast characters to unsigned char before converting to larger integer sizes A good example from the CERT description when a char variable is used to read from a file that might contain non-ASCII characters. The prob- lem comes up when the code uses the -1 integer value as EOF, while the 255 character code is also stored as -1 in two's complement form of char type. See a simple example of this below. This code stops not only when it reaches the end of the file, but also when it gets a char- acter with the 255 code. #define EOF (-1) int read(void) { char CChar; int IChar = EOF; if (readChar(CChar)) { IChar = CChar; } return IChar; } A proper way to fix the code above is converting the char variable to an unsigned char value first. #define EOF (-1) int read(void) { char CChar; int IChar = EOF; if (readChar(CChar)) { IChar = static_cast<unsigned char>(CChar); } return IChar; } Another use case is checking the equality of two char variables with different signedness. Inside the non-ASCII value range this comparison between a signed char and an unsigned char always returns false. bool compare(signed char SChar, unsigned char USChar) { if (SChar == USChar) return true; return false; } The easiest way to fix this kind of comparison is casting one of the arguments, so both arguments will have the same type. bool compare(signed char SChar, unsigned char USChar) { if (static_cast<unsigned char>(SChar) == USChar) return true; return false; } CharTypdefsToIgnore A semicolon-separated list of typedef names. In this list, we can list typedefs for char or signed char, which will be ignored by the check. This is useful when a typedef introduces an inte- ger alias like sal_Int8 or int8_t. In this case, human misinter- pretation is not an issue. DiagnoseSignedUnsignedCharComparisons When true, the check will warn on signed char/unsigned char com- parisons, otherwise these comparisons are ignored. By default, this option is set to true. bugprone-sizeof-container The check finds usages of sizeof on expressions of STL container types. Most likely the user wanted to use .size() instead. All class/struct types declared in namespace std:: having a const size() method are considered containers, with the exception of std::bitset and std::array. Examples: std::string s; int a = 47 + sizeof(s); // warning: sizeof() doesn't return the size of the container. Did you mean .size()? int b = sizeof(std::string); // no warning, probably intended. std::string array_of_strings[10]; int c = sizeof(array_of_strings) / sizeof(array_of_strings[0]); // no warning, definitely intended. std::array<int, 3> std_array; int d = sizeof(std_array); // no warning, probably intended. bugprone-sizeof-expression The check finds usages of sizeof expressions which are most likely er- rors. The sizeof operator yields the size (in bytes) of its operand, which may be an expression or the parenthesized name of a type. Misuse of this operator may be leading to errors and possible software vulnera- bilities. Suspicious usage of 'sizeof(K)' A common mistake is to query the sizeof of an integer literal. This is equivalent to query the size of its type (probably int). The intent of the programmer was probably to simply get the integer and not its size. #define BUFLEN 42 char buf[BUFLEN]; memset(buf, 0, sizeof(BUFLEN)); // sizeof(42) ==> sizeof(int) Suspicious usage of 'sizeof(expr)' In cases, where there is an enum or integer to represent a type, a com- mon mistake is to query the sizeof on the integer or enum that repre- sents the type that should be used by sizeof. This results in the size of the integer and not of the type the integer represents: enum data_type { FLOAT_TYPE, DOUBLE_TYPE }; struct data { data_type type; void* buffer; data_type get_type() { return type; } }; void f(data d, int numElements) { // should be sizeof(float) or sizeof(double), depending on d.get_type() int numBytes = numElements * sizeof(d.get_type()); ... } Suspicious usage of 'sizeof(this)' The this keyword is evaluated to a pointer to an object of a given type. The expression sizeof(this) is returning the size of a pointer. The programmer most likely wanted the size of the object and not the size of the pointer. class Point { [...] size_t size() { return sizeof(this); } // should probably be sizeof(*this) [...] }; Suspicious usage of 'sizeof(char*)' There is a subtle difference between declaring a string literal with char* A = "" and char A[] = "". The first case has the type char* in- stead of the aggregate type char[]. Using sizeof on an object declared with char* type is returning the size of a pointer instead of the num- ber of characters (bytes) in the string literal. const char* kMessage = "Hello World!"; // const char kMessage[] = "..."; void getMessage(char* buf) { memcpy(buf, kMessage, sizeof(kMessage)); // sizeof(char*) } Suspicious usage of 'sizeof(A*)' A common mistake is to compute the size of a pointer instead of its pointee. These cases may occur because of explicit cast or implicit conversion. int A[10]; memset(A, 0, sizeof(A + 0)); struct Point point; memset(point, 0, sizeof(&point)); Suspicious usage of 'sizeof(...)/sizeof(...)' Dividing sizeof expressions is typically used to retrieve the number of elements of an aggregate. This check warns on incompatible or suspi- cious cases. In the following example, the entity has 10-bytes and is incompatible with the type int which has 4 bytes. char buf[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; // sizeof(buf) => 10 void getMessage(char* dst) { memcpy(dst, buf, sizeof(buf) / sizeof(int)); // sizeof(int) => 4 [incompatible sizes] } In the following example, the expression sizeof(Values) is returning the size of char*. One can easily be fooled by its declaration, but in parameter declaration the size '10' is ignored and the function is re- ceiving a char*. char OrderedValues[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; return CompareArray(char Values[10]) { return memcmp(OrderedValues, Values, sizeof(Values)) == 0; // sizeof(Values) ==> sizeof(char*) [implicit cast to char*] } Suspicious 'sizeof' by 'sizeof' expression Multiplying sizeof expressions typically makes no sense and is probably a logic error. In the following example, the programmer used * instead of /. const char kMessage[] = "Hello World!"; void getMessage(char* buf) { memcpy(buf, kMessage, sizeof(kMessage) * sizeof(char)); // sizeof(kMessage) / sizeof(char) } This check may trigger on code using the arraysize macro. The following code is working correctly but should be simplified by using only the sizeof operator. extern Object objects[100]; void InitializeObjects() { memset(objects, 0, arraysize(objects) * sizeof(Object)); // sizeof(objects) } Suspicious usage of 'sizeof(sizeof(...))' Getting the sizeof of a sizeof makes no sense and is typically an error hidden through macros. #define INT_SZ sizeof(int) int buf[] = { 42 }; void getInt(int* dst) { memcpy(dst, buf, sizeof(INT_SZ)); // sizeof(sizeof(int)) is suspicious. } Options WarnOnSizeOfConstant When true, the check will warn on an expression like sizeof(CON- STANT). Default is true. WarnOnSizeOfIntegerExpression When true, the check will warn on an expression like sizeof(expr) where the expression results in an integer. Default is false. WarnOnSizeOfThis When true, the check will warn on an expression like sizeof(this). Default is true. WarnOnSizeOfCompareToConstant When true, the check will warn on an expression like sizeof(expr) <= k for a suspicious constant k while k is 0 or greater than 0x8000. Default is true. WarnOnSizeOfPointerToAggregate When true, the check will warn on an expression like ``sizeof(expr)` where the expression is a pointer to aggregate. Default is true. bugprone-spuriously-wake-up-functions Finds cnd_wait, cnd_timedwait, wait, wait_for, or wait_until function calls when the function is not invoked from a loop that checks whether a condition predicate holds or the function has a condition parameter. if (condition_predicate) { condition.wait(lk); } if (condition_predicate) { if (thrd_success != cnd_wait(&condition, &lock)) { } } This check corresponds to the CERT C++ Coding Standard rule CON54-CPP. Wrap functions that can spuriously wake up in a loop. and CERT C Cod- ing Standard rule CON36-C. Wrap functions that can spuriously wake up in a loop. bugprone-standalone-empty Warns when empty() is used on a range and the result is ignored. Sug- gests clear() if it is an existing member function. The empty() method on several common ranges returns a Boolean indicat- ing whether or not the range is empty, but is often mistakenly inter- preted as a way to clear the contents of a range. Some ranges offer a clear() method for this purpose. This check warns when a call to empty returns a result that is ignored, and suggests replacing it with a call to clear() if it is available as a member function of the range. For example, the following code could be used to indicate whether a range is empty or not, but the result is ignored: std::vector<int> v; ... v.empty(); A call to clear() would appropriately clear the contents of the range: std::vector<int> v; ... v.clear(); Limitations: • Doesn't warn if empty() is defined and used with the ignore result in the class template definition (for example in the library implementa- tion). These error cases can be caught with [[nodiscard]] attribute. bugprone-string-constructor Finds string constructors that are suspicious and probably errors. A common mistake is to swap parameters to the 'fill' string-construc- tor. Examples: std::string str('x', 50); // should be str(50, 'x') Calling the string-literal constructor with a length bigger than the literal is suspicious and adds extra random characters to the string. Examples: std::string("test", 200); // Will include random characters after "test". std::string_view("test", 200); Creating an empty string from constructors with parameters is consid- ered suspicious. The programmer should use the empty constructor in- stead. Examples: std::string("test", 0); // Creation of an empty string. std::string_view("test", 0); Options WarnOnLargeLength When true, the check will warn on a string with a length greater than LargeLengthThreshold. Default is true. LargeLengthThreshold An integer specifying the large length threshold. Default is 0x800000. StringNames Default is ::std::basic_string;::std::basic_string_view. Semicolon-delimited list of class names to apply this check to. By default ::std::basic_string applies to std::string and std::wstring. Set to e.g. ::std::ba- sic_string;llvm::StringRef;QString to perform this check on cus- tom classes. bugprone-string-integer-assignment The check finds assignments of an integer to std::basic_string<CharT> (std::string, std::wstring, etc.). The source of the problem is the following assignment operator of std::basic_string<CharT>: basic_string& operator=( CharT ch ); Numeric types can be implicitly casted to character types. std::string s; int x = 5965; s = 6; s = x; Use the appropriate conversion functions or character literals. std::string s; int x = 5965; s = '6'; s = std::to_string(x); In order to suppress false positives, use an explicit cast. std::string s; s = static_cast<char>(6); bugprone-string-literal-with-embedded-nul Finds occurrences of string literal with embedded NUL character and validates their usage. Invalid escaping Special characters can be escaped within a string literal by using their hexadecimal encoding like \x42. A common mistake is to escape them like this \0x42 where the \0 stands for the NUL character. const char* Example[] = "Invalid character: \0x12 should be \x12"; const char* Bytes[] = "\x03\0x02\0x01\0x00\0xFF\0xFF\0xFF"; Truncated literal String-like classes can manipulate strings with embedded NUL as they are keeping track of the bytes and the length. This is not the case for a char* (NUL-terminated) string. A common mistake is to pass a string-literal with embedded NUL to a string constructor expecting a NUL-terminated string. The bytes after the first NUL character are truncated. std::string str("abc\0def"); // "def" is truncated str += "\0"; // This statement is doing nothing if (str == "\0abc") return; // This expression is always true bugprone-stringview-nullptr Checks for various ways that the const CharT* constructor of std::ba- sic_string_view can be passed a null argument and replaces them with the default constructor in most cases. For the comparison operators, braced initializer list does not compile so instead a call to .empty() or the empty string literal are used, where appropriate. This prevents code from invoking behavior which is unconditionally un- defined. The single-argument const CharT* constructor does not check for the null case before dereferencing its input. The standard is slated to add an explicitly-deleted overload to catch some of these cases: wg21.link/p2166 To catch the additional cases of NULL (which expands to __null) and 0, first run the modernize-use-nullptr check to convert the callers to nullptr. std::string_view sv = nullptr; sv = nullptr; bool is_empty = sv == nullptr; bool isnt_empty = sv != nullptr; accepts_sv(nullptr); accepts_sv({{}}); // A accepts_sv({nullptr, 0}); // B is translated into... std::string_view sv = {}; sv = {}; bool is_empty = sv.empty(); bool isnt_empty = !sv.empty(); accepts_sv(""); accepts_sv(""); // A accepts_sv({nullptr, 0}); // B NOTE: The source pattern with trailing comment "A" selects the (const CharT*) constructor overload and then value-initializes the pointer, causing a null dereference. It happens to not include the nullptr literal, but it is still within the scope of this ClangTidy check. NOTE: The source pattern with trailing comment "B" selects the (const CharT*, size_type) constructor which is perfectly valid, since the length argument is 0. It is not changed by this ClangTidy check. bugprone-suspicious-enum-usage The checker detects various cases when an enum is probably misused (as a bitmask ). 1. When "ADD" or "bitwise OR" is used between two enum which come from different types and these types value ranges are not disjoint. The following cases will be investigated only using StrictMode. We re- gard the enum as a (suspicious) bitmask if the three conditions below are true at the same time: • at most half of the elements of the enum are non pow-of-2 numbers (because of short enumerations) • there is another non pow-of-2 number than the enum constant repre- senting all choices (the result "bitwise OR" operation of all enum elements) • enum type variable/enumconstant is used as an argument of a + or "bitwise OR " operator So whenever the non pow-of-2 element is used as a bitmask element we diagnose a misuse and give a warning. 2. Investigating the right hand side of += and |= operator. 3. Check only the enum value side of a | and + operator if one of them is not enum val. 4. Check both side of | or + operator where the enum values are from the same enum type. Examples: enum { A, B, C }; enum { D, E, F = 5 }; enum { G = 10, H = 11, I = 12 }; unsigned flag; flag = A | H; // OK, disjoint value intervals in the enum types ->probably good use. flag = B | F; // Warning, have common values so they are probably misused. // Case 2: enum Bitmask { A = 0, B = 1, C = 2, D = 4, E = 8, F = 16, G = 31 // OK, real bitmask. }; enum Almostbitmask { AA = 0, BB = 1, CC = 2, DD = 4, EE = 8, FF = 16, GG // Problem, forgot to initialize. }; unsigned flag = 0; flag |= E; // OK. flag |= EE; // Warning at the decl, and note that it was used here as a bitmask. Options StrictMode Default value: 0. When non-null the suspicious bitmask usage will be investigated additionally to the different enum usage check. bugprone-suspicious-include The check detects various cases when an include refers to what appears to be an implementation file, which often leads to hard-to-track-down ODR violations. Examples: #include "Dinosaur.hpp" // OK, .hpp files tend not to have definitions. #include "Pterodactyl.h" // OK, .h files tend not to have definitions. #include "Velociraptor.cpp" // Warning, filename is suspicious. #include_next <stdio.c> // Warning, filename is suspicious. Options HeaderFileExtensions Note: this option is deprecated, it will be removed in clang-tidy version 19. Please use the global configuration op- tion HeaderFileExtensions. Default value: ";h;hh;hpp;hxx" A semicolon-separated list of filename extensions of header files (the filename extensions should not contain a "." prefix). For extension-less header files, use an empty string or leave an empty string between ";" if there are other filename extensions. ImplementationFileExtensions Note: this option is deprecated, it will be removed in clang-tidy version 19. Please use the global configuration op- tion ImplementationFileExtensions. Default value: "c;cc;cpp;cxx" Likewise, a semicolon-separated list of filename extensions of implementation files. bugprone-suspicious-memory-comparison Finds potentially incorrect calls to memcmp() based on properties of the arguments. The following cases are covered: Case 1: Non-standard-layout type Comparing the object representations of non-standard-layout objects may not properly compare the value representations. Case 2: Types with no unique object representation Objects with the same value may not have the same object representa- tion. This may be caused by padding or floating-point types. See also: EXP42-C. Do not compare padding data and FLP37-C. Do not use object representations to compare floating-point values This check is also related to and partially overlaps the CERT C++ Cod- ing Standard rules OOP57-CPP. Prefer special member functions and over- loaded operators to C Standard Library functions and EXP62-CPP. Do not access the bits of an object representation that are not part of the object's value representation bugprone-suspicious-memset-usage This check finds memset() calls with potential mistakes in their argu- ments. Considering the function as void* memset(void* destination, int fill_value, size_t byte_count), the following cases are covered: Case 1: Fill value is a character ``'0'`` Filling up a memory area with ASCII code 48 characters is not custom- ary, possibly integer zeroes were intended instead. The check offers a replacement of '0' with 0. Memsetting character pointers with '0' is allowed. Case 2: Fill value is truncated Memset converts fill_value to unsigned char before using it. If fill_value is out of unsigned character range, it gets truncated and memory will not contain the desired pattern. Case 3: Byte count is zero Calling memset with a literal zero in its byte_count argument is likely to be unintended and swapped with fill_value. The check offers to swap these two arguments. Corresponding cpplint.py check name: runtime/memset. Examples: void foo() { int i[5] = {1, 2, 3, 4, 5}; int *ip = i; char c = '1'; char *cp = &c; int v = 0; // Case 1 memset(ip, '0', 1); // suspicious memset(cp, '0', 1); // OK // Case 2 memset(ip, 0xabcd, 1); // fill value gets truncated memset(ip, 0x00, 1); // OK // Case 3 memset(ip, sizeof(int), v); // zero length, potentially swapped memset(ip, 0, 1); // OK } bugprone-suspicious-missing-comma String literals placed side-by-side are concatenated at translation phase 6 (after the preprocessor). This feature is used to represent long string literal on multiple lines. For instance, the following declarations are equivalent: const char* A[] = "This is a test"; const char* B[] = "This" " is a " "test"; A common mistake done by programmers is to forget a comma between two string literals in an array initializer list. const char* Test[] = { "line 1", "line 2" // Missing comma! "line 3", "line 4", "line 5" }; The array contains the string "line 2line3" at offset 1 (i.e. Test[1]). Clang won't generate warnings at compile time. This check may warn incorrectly on cases like: const char* SupportedFormat[] = { "Error %s", "Code " PRIu64, // May warn here. "Warning %s", }; Options SizeThreshold An unsigned integer specifying the minimum size of a string lit- eral to be considered by the check. Default is 5U. RatioThreshold A string specifying the maximum threshold ratio [0, 1.0] of sus- picious string literals to be considered. Default is ".2". MaxConcatenatedTokens An unsigned integer specifying the maximum number of concate- nated tokens. Default is 5U. bugprone-suspicious-realloc-usage This check finds usages of realloc where the return value is assigned to the same expression as passed to the first argument: p = realloc(p, size); The problem with this construct is that if realloc fails it re- turns a null pointer but does not deallocate the original memory. If no other variable is pointing to it, the original memory block is not available any more for the program to use or free. In either case p = realloc(p, size); indicates bad coding style and can be replaced by q = realloc(p, size);. The pointer expression (used at realloc) can be a variable or a field member of a data structure, but can not contain function calls or unre- solved types. In obvious cases when the pointer used at realloc is assigned to an- other variable before the realloc call, no warning is emitted. This happens only if a simple expression in form of q = p or void *q = p is found in the same function where p = realloc(p, ...) is found. The as- signment has to be before the call to realloc (but otherwise at any place) in the same function. This suppression works only if p is a single variable. Examples: struct A { void *p; }; A &getA(); void foo(void *p, A *a, int new_size) { p = realloc(p, new_size); // warning: 'p' may be set to null if 'realloc' fails, which may result in a leak of the original buffer a->p = realloc(a->p, new_size); // warning: 'a->p' may be set to null if 'realloc' fails, which may result in a leak of the original buffer getA().p = realloc(getA().p, new_size); // no warning } void foo1(void *p, int new_size) { void *p1 = p; p = realloc(p, new_size); // no warning } bugprone-suspicious-semicolon Finds most instances of stray semicolons that unexpectedly alter the meaning of the code. More specifically, it looks for if, while, for and for-range statements whose body is a single semicolon, and then ana- lyzes the context of the code (e.g. indentation) in an attempt to de- termine whether that is intentional. if (x < y); { x++; } Here the body of the if statement consists of only the semicolon at the end of the first line, and x will be incremented regardless of the con- dition. while ((line = readLine(file)) != NULL); processLine(line); As a result of this code, processLine() will only be called once, when the while loop with the empty body exits with line == NULL. The inden- tation of the code indicates the intention of the programmer. if (x >= y); x -= y; While the indentation does not imply any nesting, there is simply no valid reason to have an if statement with an empty body (but it can make sense for a loop). So this check issues a warning for the code above. To solve the issue remove the stray semicolon or in case the empty body is intentional, reflect this using code indentation or put the semi- colon in a new line. For example: while (readWhitespace()); Token t = readNextToken(); Here the second line is indented in a way that suggests that it is meant to be the body of the while loop - whose body is in fact empty, because of the semicolon at the end of the first line. Either remove the indentation from the second line: while (readWhitespace()); Token t = readNextToken(); ... or move the semicolon from the end of the first line to a new line: while (readWhitespace()) ; Token t = readNextToken(); In this case the check will assume that you know what you are doing, and will not raise a warning. bugprone-suspicious-string-compare Find suspicious usage of runtime string comparison functions. This check is valid in C and C++. Checks for calls with implicit comparator and proposed to explicitly add it. if (strcmp(...)) // Implicitly compare to zero if (!strcmp(...)) // Won't warn if (strcmp(...) != 0) // Won't warn Checks that compare function results (i.e., strcmp) are compared to valid constant. The resulting value is < 0 when lower than, > 0 when greater than, == 0 when equals. A common mistake is to compare the result to 1 or -1. if (strcmp(...) == -1) // Incorrect usage of the returned value. Additionally, the check warns if the results value is implicitly cast to a suspicious non-integer type. It's happening when the returned value is used in a wrong context. if (strcmp(...) < 0.) // Incorrect usage of the returned value. Options WarnOnImplicitComparison When true, the check will warn on implicit comparison. true by default. WarnOnLogicalNotComparison When true, the check will warn on logical not comparison. false by default. StringCompareLikeFunctions A string specifying the comma-separated names of the extra string comparison functions. Default is an empty string. The check will detect the following string comparison functions: __builtin_memcmp, __builtin_strcasecmp, __builtin_strcmp, __builtin_strncasecmp, __builtin_strncmp, _mbscmp, _mbscmp_l, _mbsicmp, _mbsicmp_l, _mbsnbcmp, _mbsnbcmp_l, _mbsnbicmp, _mb- snbicmp_l, _mbsncmp, _mbsncmp_l, _mbsnicmp, _mbsnicmp_l, _memicmp, _memicmp_l, _stricmp, _stricmp_l, _strnicmp, _str- nicmp_l, _wcsicmp, _wcsicmp_l, _wcsnicmp, _wcsnicmp_l, lstrcmp, lstrcmpi, memcmp, memicmp, strcasecmp, strcmp, strcmpi, stricmp, strncasecmp, strncmp, strnicmp, wcscasecmp, wcscmp, wcsicmp, wc- sncmp, wcsnicmp, wmemcmp. bugprone-swapped-arguments Finds potentially swapped arguments by examining implicit conversions. It analyzes the types of the arguments being passed to a function and compares them to the expected types of the corresponding parameters. If there is a mismatch or an implicit conversion that indicates a poten- tial swap, a warning is raised. void printNumbers(int a, float b); int main() { // Swapped arguments: float passed as int, int as float) printNumbers(10.0f, 5); return 0; } Covers a wide range of implicit conversions, including: - User-defined conversions - Conversions from floating-point types to boolean or inte- gral types - Conversions from integral types to boolean or float- ing-point types - Conversions from boolean to integer types or float- ing-point types - Conversions from (member) pointers to boolean It is important to note that for most argument swaps, the types need to match exactly. However, there are exceptions to this rule. Specifi- cally, when the swapped argument is of integral type, an exact match is not always necessary. Implicit casts from other integral types are also accepted. Similarly, when dealing with floating-point arguments, implicit casts between different floating-point types are considered acceptable. To avoid confusion, swaps where both swapped arguments are of integral types or both are of floating-point types do not trigger the warning. In such cases, it's assumed that the developer intentionally used dif- ferent integral or floating-point types and does not raise a warning. This approach prevents false positives and provides flexibility in han- dling situations where varying integral or floating-point types are in- tentionally utilized. bugprone-switch-missing-default-case Ensures that switch statements without default cases are flagged, fo- cuses only on covering cases with non-enums where the compiler may not issue warnings. Switch statements without a default case can lead to unexpected behav- ior and incomplete handling of all possible cases. When a switch state- ment lacks a default case, if a value is encountered that does not match any of the specified cases, the program will continue execution without any defined behavior or handling. This check helps identify switch statements that are missing a default case, allowing developers to ensure that all possible cases are handled properly. Adding a default case allows for graceful handling of unex- pected or unmatched values, reducing the risk of program errors and un- expected behavior. Example: // Example 1: // warning: switching on non-enum value without default case may not cover all cases switch (i) { case 0: break; } // Example 2: enum E { eE1 }; E e = eE1; switch (e) { // no-warning case eE1: break; } // Example 3: int i = 0; switch (i) { // no-warning case 0: break; default: break; } NOTE: Enum types are already covered by compiler warnings (comes under -Wswitch) when a switch statement does not handle all enum values. This check focuses on non-enum types where the compiler warnings may not be present. SEE ALSO: The CppCoreGuideline ES.79 provide guidelines on switch statements, including the recommendation to always provide a default case. bugprone-terminating-continue Detects do while loops with a condition always evaluating to false that have a continue statement, as this continue terminates the loop effec- tively. void f() { do { // some code continue; // terminating continue // some other code } while(false); bugprone-throw-keyword-missing Warns about a potentially missing throw keyword. If a temporary object is created, but the object's type derives from (or is the same as) a class that has 'EXCEPTION', 'Exception' or 'exception' in its name, we can assume that the programmer's intention was to throw that object. Example: void f(int i) { if (i < 0) { // Exception is created but is not thrown. std::runtime_error("Unexpected argument"); } } bugprone-too-small-loop-variable Detects those for loops that have a loop variable with a "too small" type which means this type can't represent all values which are part of the iteration range. int main() { long size = 294967296l; for (short i = 0; i < size; ++i) {} } This for loop is an infinite loop because the short type can't repre- sent all values in the [0..size] interval. In a real use case size means a container's size which depends on the user input. int doSomething(const std::vector& items) { for (short i = 0; i < items.size(); ++i) {} } This algorithm works for a small amount of objects, but will lead to freeze for a larger user input. MagnitudeBitsUpperLimit Upper limit for the magnitude bits of the loop variable. If it's set the check filters out those catches in which the loop vari- able's type has more magnitude bits as the specified upper limit. The default value is 16. For example, if the user sets this option to 31 (bits), then a 32-bit unsigned int is ignored by the check, however a 32-bit int is not (A 32-bit signed int has 31 magnitude bits). int main() { long size = 294967296l; for (unsigned i = 0; i < size; ++i) {} // no warning with MagnitudeBitsUpperLimit = 31 on a system where unsigned is 32-bit for (int i = 0; i < size; ++i) {} // warning with MagnitudeBitsUpperLimit = 31 on a system where int is 32-bit } bugprone-unchecked-optional-access Note: This check uses a flow-sensitive static analysis to produce its results. Therefore, it may be more resource intensive (RAM, CPU) than the average clang-tidy check. This check identifies unsafe accesses to values contained in std::op- tional<T>, absl::optional<T>, base::Optional<T>, or folly::Optional<T> objects. Below we will refer to all these types collectively as op- tional<T>. An access to the value of an optional<T> occurs when one of its value, operator*, or operator-> member functions is invoked. To align with common misconceptions, the check considers these member functions as equivalent, even though there are subtle differences related to excep- tions versus undefined behavior. See Additional notes, below, for more information on this topic. An access to the value of an optional<T> is considered safe if and only if code in the local scope (for example, a function body) ensures that the optional<T> has a value in all possible execution paths that can reach the access. That should happen either through an explicit check, using the optional<T>::has_value member function, or by constructing the optional<T> in a way that shows that it unambiguously holds a value (e.g using std::make_optional which always returns a populated std::op- tional<T>). Below we list some examples, starting with unsafe optional access pat- terns, followed by safe access patterns. Unsafe access patterns Access the value without checking if it exists The check flags accesses to the value that are not locally guarded by existence check: void f(std::optional<int> opt) { use(*opt); // unsafe: it is unclear whether `opt` has a value. } Access the value in the wrong branch The check is aware of the state of an optional object in different branches of the code. For example: void f(std::optional<int> opt) { if (opt.has_value()) { } else { use(opt.value()); // unsafe: it is clear that `opt` does *not* have a value. } } Assume a function result to be stable The check is aware that function results might not be stable. That is, consecutive calls to the same function might return different values. For example: void f(Foo foo) { if (foo.opt().has_value()) { use(*foo.opt()); // unsafe: it is unclear whether `foo.opt()` has a value. } } Rely on invariants of uncommon APIs The check is unaware of invariants of uncommon APIs. For example: void f(Foo foo) { if (foo.HasProperty("bar")) { use(*foo.GetProperty("bar")); // unsafe: it is unclear whether `foo.GetProperty("bar")` has a value. } } Check if a value exists, then pass the optional to another function The check relies on local reasoning. The check and value access must both happen in the same function. An access is considered unsafe even if the caller of the function performing the access ensures that the optional has a value. For example: void g(std::optional<int> opt) { use(*opt); // unsafe: it is unclear whether `opt` has a value. } void f(std::optional<int> opt) { if (opt.has_value()) { g(opt); } } Safe access patterns Check if a value exists, then access the value The check recognizes all straightforward ways for checking if a value exists and accessing the value contained in an optional object. For ex- ample: void f(std::optional<int> opt) { if (opt.has_value()) { use(*opt); } } Check if a value exists, then access the value from a copy The criteria that the check uses is semantic, not syntactic. It recog- nizes when a copy of the optional object being accessed is known to have a value. For example: void f(std::optional<int> opt1) { if (opt1.has_value()) { std::optional<int> opt2 = opt1; use(*opt2); } } Ensure that a value exists using common macros The check is aware of common macros like CHECK and DCHECK. Those can be used to ensure that an optional object has a value. For example: void f(std::optional<int> opt) { DCHECK(opt.has_value()); use(*opt); } Ensure that a value exists, then access the value in a correlated branch The check is aware of correlated branches in the code and can figure out when an optional object is ensured to have a value on all execution paths that lead to an access. For example: void f(std::optional<int> opt) { bool safe = false; if (opt.has_value() && SomeOtherCondition()) { safe = true; } // ... more code... if (safe) { use(*opt); } } Stabilize function results Since function results are not assumed to be stable across calls, it is best to store the result of the function call in a local variable and use that variable to access the value. For example: void f(Foo foo) { if (const auto& foo_opt = foo.opt(); foo_opt.has_value()) { use(*foo_opt); } } Do not rely on uncommon-API invariants When uncommon APIs guarantee that an optional has contents, do not rely on it -- instead, check explicitly that the optional object has a value. For example: void f(Foo foo) { if (const auto& property = foo.GetProperty("bar")) { use(*property); } } instead of the HasProperty, GetProperty pairing we saw above. Do not rely on caller-performed checks If you know that all of a function's callers have checked that an op- tional argument has a value, either change the function to take the value directly or check the optional again in the local scope of the callee. For example: void g(int val) { use(val); } void f(std::optional<int> opt) { if (opt.has_value()) { g(*opt); } } and struct S { std::optional<int> opt; int x; }; void g(const S &s) { if (s.opt.has_value() && s.x > 10) { use(*s.opt); } void f(S s) { if (s.opt.has_value()) { g(s); } } Additional notes Aliases created via using declarations The check is aware of aliases of optional types that are created via using declarations. For example: using OptionalInt = std::optional<int>; void f(OptionalInt opt) { use(opt.value()); // unsafe: it is unclear whether `opt` has a value. } Lambdas The check does not currently report unsafe optional accesses in lamb- das. A future version will expand the scope to lambdas, following the rules outlined above. It is best to follow the same principles when us- ing optionals in lambdas. Access with operator*() vs. value() Given that value() has well-defined behavior (either throwing an excep- tion or terminating the program), why treat it the same as operator*() which causes undefined behavior (UB)? That is, why is it considered un- safe to access an optional with value(), if it's not provably populated with a value? For that matter, why is CHECK() followed by operator*() any better than value(), given that they are semantically equivalent (on configurations that disable exceptions)? The answer is that we assume most users do not realize the difference between value() and operator*(). Shifting to operator*() and some form of explicit value-presence check or explicit program termination has two advantages: • Readability. The check, and any potential side effects like pro- gram shutdown, are very clear in the code. Separating access from checks can actually make the checks more obvious. • Performance. A single check can cover many or even all accesses within scope. This gives the user the best of both worlds -- the safety of a dynamic check, but without incurring redundant costs. bugprone-undefined-memory-manipulation Finds calls of memory manipulation functions memset(), memcpy() and memmove() on non-TriviallyCopyable objects resulting in undefined be- havior. Using memory manipulation functions on non-TriviallyCopyable objects can lead to a range of subtle and challenging issues in C++ code. The most immediate concern is the potential for undefined behavior, where the state of the object may become corrupted or invalid. This can mani- fest as crashes, data corruption, or unexpected behavior at runtime, making it challenging to identify and diagnose the root cause. Addi- tionally, misuse of memory manipulation functions can bypass essential object-specific operations, such as constructors and destructors, lead- ing to resource leaks or improper initialization. For example, when using memcpy to copy std::string, pointer data is be- ing copied, and it can result in a double free issue. #include <cstring> #include <string> int main() { std::string source = "Hello"; std::string destination; std::memcpy(&destination, &source, sizeof(std::string)); // Undefined behavior may occur here, during std::string destructor call. return 0; } bugprone-undelegated-constructor Finds creation of temporary objects in constructors that look like a function call to another constructor of the same class. The user most likely meant to use a delegating constructor or base class initializer. bugprone-unhandled-exception-at-new Finds calls to new with missing exception handler for std::bad_alloc. Calls to new may throw exceptions of type std::bad_alloc that should be handled. Alternatively, the nonthrowing form of new can be used. The check verifies that the exception is handled in the function that calls new. If a nonthrowing version is used or the exception is allowed to propa- gate out of the function no warning is generated. The exception handler is checked if it catches a std::bad_alloc or std::exception exception type, or all exceptions (catch-all). The check assumes that any user-defined operator new is either noexcept or may throw an exception of type std::bad_alloc (or one derived from it). Other exception class types are not taken into account. int *f() noexcept { int *p = new int[1000]; // warning: missing exception handler for allocation failure at 'new' // ... return p; } int *f1() { // not 'noexcept' int *p = new int[1000]; // no warning: exception can be handled outside // of this function // ... return p; } int *f2() noexcept { try { int *p = new int[1000]; // no warning: exception is handled // ... return p; } catch (std::bad_alloc &) { // ... } // ... } int *f3() noexcept { int *p = new (std::nothrow) int[1000]; // no warning: "nothrow" is used // ... return p; } bugprone-unhandled-self-assignment cert-oop54-cpp redirects here as an alias for this check. For the CERT alias, the WarnOnlyIfThisHasSuspiciousField option is set to false. Finds user-defined copy assignment operators which do not protect the code against self-assignment either by checking self-assignment explic- itly or using the copy-and-swap or the copy-and-move method. By default, this check searches only those classes which have any pointer or C array field to avoid false positives. In case of a pointer or a C array, it's likely that self-copy assignment breaks the object if the copy assignment operator was not written with care. See also: OOP54-CPP. Gracefully handle self-copy assignment A copy assignment operator must prevent that self-copy assignment ruins the object state. A typical use case is when the class has a pointer field and the copy assignment operator first releases the pointed ob- ject and then tries to assign it: class T { int* p; public: T(const T &rhs) : p(rhs.p ? new int(*rhs.p) : nullptr) {} ~T() { delete p; } // ... T& operator=(const T &rhs) { delete p; p = new int(*rhs.p); return *this; } }; There are two common C++ patterns to avoid this problem. The first is the self-assignment check: class T { int* p; public: T(const T &rhs) : p(rhs.p ? new int(*rhs.p) : nullptr) {} ~T() { delete p; } // ... T& operator=(const T &rhs) { if(this == &rhs) return *this; delete p; p = new int(*rhs.p); return *this; } }; The second one is the copy-and-swap method when we create a temporary copy (using the copy constructor) and then swap this temporary object with this: class T { int* p; public: T(const T &rhs) : p(rhs.p ? new int(*rhs.p) : nullptr) {} ~T() { delete p; } // ... void swap(T &rhs) { using std::swap; swap(p, rhs.p); } T& operator=(const T &rhs) { T(rhs).swap(*this); return *this; } }; There is a third pattern which is less common. Let's call it the copy-and-move method when we create a temporary copy (using the copy constructor) and then move this temporary object into this (needs a move assignment operator): class T { int* p; public: T(const T &rhs) : p(rhs.p ? new int(*rhs.p) : nullptr) {} ~T() { delete p; } // ... T& operator=(const T &rhs) { T t = rhs; *this = std::move(t); return *this; } T& operator=(T &&rhs) { p = rhs.p; rhs.p = nullptr; return *this; } }; WarnOnlyIfThisHasSuspiciousField When true, the check will warn only if the container class of the copy assignment operator has any suspicious fields (pointer or C array). This option is set to true by default. bugprone-unique-ptr-array-mismatch Finds initializations of C++ unique pointers to non-array type that are initialized with an array. If a pointer std::unique_ptr<T> is initialized with a new-expression new T[] the memory is not deallocated correctly. A plain delete is used in this case to deallocate the target memory. Instead a delete[] call is needed. A std::unique_ptr<T[]> uses the correct delete operator. The check does not emit warning if an unique_ptr with user-specified deleter type is used. The check offers replacement of unique_ptr<T> to unique_ptr<T[]> if it is used at a single variable declaration (one variable in one state- ment). Example: std::unique_ptr<Foo> x(new Foo[10]); // -> std::unique_ptr<Foo[]> x(new Foo[10]); // ^ warning: unique pointer to non-array is initialized with array std::unique_ptr<Foo> x1(new Foo), x2(new Foo[10]); // no replacement // ^ warning: unique pointer to non-array is initialized with array D d; std::unique_ptr<Foo, D> x3(new Foo[10], d); // no warning (custom deleter used) struct S { std::unique_ptr<Foo> x(new Foo[10]); // no replacement in this case // ^ warning: unique pointer to non-array is initialized with array }; This check partially covers the CERT C++ Coding Standard rule MEM51-CPP. Properly deallocate dynamically allocated resources However, only the std::unique_ptr case is detected by this check. bugprone-unsafe-functions Checks for functions that have safer, more secure replacements avail- able, or are considered deprecated due to design flaws. The check heavily relies on the functions from the Annex K. "Bounds-checking in- terfaces" of C11. The check implements the following rules from the CERT C Coding Stan- dard: • Recommendation MSC24-C. Do not use deprecated or obsolescent functions. • Rule MSC33-C. Do not pass invalid data to the asctime() func- tion. cert-msc24-c and cert-msc33-c redirect here as aliases of this check. Unsafe functions If Annex K. is available, a replacement from Annex K. is suggested for the following functions: asctime, asctime_r, bsearch, ctime, fopen, fprintf, freopen, fscanf, fwprintf, fwscanf, getenv, gets, gmtime, localtime, mbsrtowcs, mb- stowcs, memcpy, memmove, memset, printf, qsort, scanf, snprintf, sprintf, sscanf, strcat, strcpy, strerror, strlen, strncat, strncpy, strtok, swprintf, swscanf, vfprintf, vfscanf, vfwprintf, vfwscanf, vprintf, vscanf, vsnprintf, vsprintf, vsscanf, vswprintf, vswscanf, vw- printf, vwscanf, wcrtomb, wcscat, wcscpy, wcslen, wcsncat, wcsncpy, wc- srtombs, wcstok, wcstombs, wctomb, wmemcpy, wmemmove, wprintf, wscanf. If Annex K. is not available, replacements are suggested only for the following functions from the previous list: • asctime, asctime_r, suggested replacement: strftime • gets, suggested replacement: fgets The following functions are always checked, regardless of Annex K availability: • rewind, suggested replacement: fseek • setbuf, suggested replacement: setvbuf If ReportMoreUnsafeFunctions is enabled, the following functions are also checked: • bcmp, suggested replacement: memcmp • bcopy, suggested replacement: memcpy_s if Annex K is available, or memcpy • bzero, suggested replacement: memset_s if Annex K is available, or memset • getpw, suggested replacement: getpwuid • vfork, suggested replacement: posix_spawn Although mentioned in the associated CERT rules, the following func- tions are ignored by the check: atof, atoi, atol, atoll, tmpfile. The availability of Annex K is determined based on the following macros: • __STDC_LIB_EXT1__: feature macro, which indicates the presence of Annex K. "Bounds-checking interfaces" in the library implementa- tion • __STDC_WANT_LIB_EXT1__: user-defined macro, which indicates that the user requests the functions from Annex K. to be defined. Both macros have to be defined to suggest replacement functions from Annex K. __STDC_LIB_EXT1__ is defined by the library implementation, and __STDC_WANT_LIB_EXT1__ must be defined to 1 by the user before in- cluding any system headers. Options ReportMoreUnsafeFunctions When true, additional functions from widely used APIs (such as POSIX) are added to the list of reported functions. See the main documentation of the check for the complete list as to what this option enables. Default is true. Examples #ifndef __STDC_LIB_EXT1__ #error "Annex K is not supported by the current standard library implementation." #endif #define __STDC_WANT_LIB_EXT1__ 1 #include <string.h> // Defines functions from Annex K. #include <stdio.h> enum { BUFSIZE = 32 }; void Unsafe(const char *Msg) { static const char Prefix[] = "Error: "; static const char Suffix[] = "\n"; char Buf[BUFSIZE] = {0}; strcpy(Buf, Prefix); // warning: function 'strcpy' is not bounds-checking; 'strcpy_s' should be used instead. strcat(Buf, Msg); // warning: function 'strcat' is not bounds-checking; 'strcat_s' should be used instead. strcat(Buf, Suffix); // warning: function 'strcat' is not bounds-checking; 'strcat_s' should be used instead. if (fputs(buf, stderr) < 0) { // error handling return; } } void UsingSafeFunctions(const char *Msg) { static const char Prefix[] = "Error: "; static const char Suffix[] = "\n"; char Buf[BUFSIZE] = {0}; if (strcpy_s(Buf, BUFSIZE, Prefix) != 0) { // error handling return; } if (strcat_s(Buf, BUFSIZE, Msg) != 0) { // error handling return; } if (strcat_s(Buf, BUFSIZE, Suffix) != 0) { // error handling return; } if (fputs(Buf, stderr) < 0) { // error handling return; } } bugprone-unused-local-non-trivial-variable Warns when a local non trivial variable is unused within a function. The following types of variables are excluded from this check: • trivial and trivially copyable • references and pointers • exception variables in catch clauses • static or thread local • structured bindings This check can be configured to warn on all non-trivial variables by setting IncludeTypes to .*, and excluding specific types using Exclude- Types. In the this example, my_lock would generate a warning that it is un- used. std::mutex my_lock; // my_lock local variable is never used In the next example, future2 would generate a warning that it is un- used. std::future<MyObject> future1; std::future<MyObject> future2; // ... MyObject foo = future1.get(); // future2 is not used. Options IncludeTypes Semicolon-separated list of regular expressions matching types of variables to check. By default the following types are checked: • ::std::.*mutex • ::std::future • ::std::basic_string • ::std::basic_regex • ::std::basic_istringstream • ::std::basic_stringstream • ::std::bitset • ::std::filesystem::path ExcludeTypes A semicolon-separated list of regular expressions matching types that are excluded from the IncludeTypes matches. By default it is an empty list. bugprone-unused-raii Finds temporaries that look like RAII objects. The canonical example for this is a scoped lock. { scoped_lock(&global_mutex); critical_section(); } The destructor of the scoped_lock is called before the critical_section is entered, leaving it unprotected. We apply a number of heuristics to reduce the false positive count of this check: • Ignore code expanded from macros. Testing frameworks make heavy use of this. • Ignore types with trivial destructors. They are very unlikely to be RAII objects and there's no difference when they are deleted. • Ignore objects at the end of a compound statement (doesn't change be- havior). • Ignore objects returned from a call. bugprone-unused-return-value Warns on unused function return values. The checked functions can be configured. Options CheckedFunctions Semicolon-separated list of functions to check. The function is checked if the name and scope matches, with any arguments. By default the following functions are checked: std::async, std::launder, std::remove, std::remove_if, std::unique, std::unique_ptr::release, std::basic_string::empty, std::vec- tor::empty, std::back_inserter, std::distance, std::find, std::find_if, std::inserter, std::lower_bound, std::make_pair, std::map::count, std::map::find, std::map::lower_bound, std::multimap::equal_range, std::multimap::upper_bound, std::set::count, std::set::find, std::setfill, std::setpreci- sion, std::setw, std::upper_bound, std::vector::at, bsearch, ferror, feof, isalnum, isalpha, isblank, iscntrl, isdigit, is- graph, islower, isprint, ispunct, isspace, isupper, iswalnum, iswprint, iswspace, isxdigit, memchr, memcmp, strcmp, strcoll, strncmp, strpbrk, strrchr, strspn, strstr, wcscmp, access, bind, connect, difftime, dlsym, fnmatch, getaddrinfo, getopt, htonl, htons, iconv_open, inet_addr, isascii, isatty, mmap, newlocale, openat, pathconf, pthread_equal, pthread_getspecific, pthread_mutex_trylock, readdir, readlink, recvmsg, regexec, scandir, semget, setjmp, shm_open, shmget, sigismember, str- casecmp, strsignal, ttyname • std::async(). Not using the return value makes the call syn- chronous. • std::launder(). Not using the return value usually means that the function interface was misunderstood by the programmer. Only the returned pointer is "laundered", not the argument. • std::remove(), std::remove_if() and std::unique(). The re- turned iterator indicates the boundary between elements to keep and elements to be removed. Not using the return value means that the information about which elements to remove is lost. • std::unique_ptr::release(). Not using the return value can lead to resource leaks if the same pointer isn't stored any- where else. Often, ignoring the release() return value indi- cates that the programmer confused the function with reset(). • std::basic_string::empty() and std::vector::empty(). Not using the return value often indicates that the programmer confused the function with clear(). CheckedReturnTypes Semicolon-separated list of function return types to check. By default the following function return types are checked: ::std::error_code, ::std::error_condition, ::std::errc, ::std::expected, ::boost::system::error_code AllowCastToVoid Controls whether casting return values to void is permitted. De- fault: false. cert-err33-c is an alias of this check that checks a fixed and large set of standard library functions. bugprone-use-after-move Warns if an object is used after it has been moved, for example: std::string str = "Hello, world!\n"; std::vector<std::string> messages; messages.emplace_back(std::move(str)); std::cout << str; The last line will trigger a warning that str is used after it has been moved. The check does not trigger a warning if the object is reinitialized af- ter the move and before the use. For example, no warning will be output for this code: messages.emplace_back(std::move(str)); str = "Greetings, stranger!\n"; std::cout << str; Subsections below explain more precisely what exactly the check consid- ers to be a move, use, and reinitialization. The check takes control flow into account. A warning is only emitted if the use can be reached from the move. This means that the following code does not produce a warning: if (condition) { messages.emplace_back(std::move(str)); } else { std::cout << str; } On the other hand, the following code does produce a warning: for (int i = 0; i < 10; ++i) { std::cout << str; messages.emplace_back(std::move(str)); } (The use-after-move happens on the second iteration of the loop.) In some cases, the check may not be able to detect that two branches are mutually exclusive. For example (assuming that i is an int): if (i == 1) { messages.emplace_back(std::move(str)); } if (i == 2) { std::cout << str; } In this case, the check will erroneously produce a warning, even though it is not possible for both the move and the use to be executed. More formally, the analysis is flow-sensitive but not path-sensitive. Silencing erroneous warnings An erroneous warning can be silenced by reinitializing the object after the move: if (i == 1) { messages.emplace_back(std::move(str)); str = ""; } if (i == 2) { std::cout << str; } If you want to avoid the overhead of actually reinitializing the ob- ject, you can create a dummy function that causes the check to assume the object was reinitialized: template <class T> void IS_INITIALIZED(T&) {} You can use this as follows: if (i == 1) { messages.emplace_back(std::move(str)); } if (i == 2) { IS_INITIALIZED(str); std::cout << str; } The check will not output a warning in this case because passing the object to a function as a non-const pointer or reference counts as a reinitialization (see section Reinitialization below). Unsequenced moves, uses, and reinitializations In many cases, C++ does not make any guarantees about the order in which sub-expressions of a statement are evaluated. This means that in code like the following, it is not guaranteed whether the use will hap- pen before or after the move: void f(int i, std::vector<int> v); std::vector<int> v = { 1, 2, 3 }; f(v[1], std::move(v)); In this kind of situation, the check will note that the use and move are unsequenced. The check will also take sequencing rules into account when reinitial- izations occur in the same statement as moves or uses. A reinitializa- tion is only considered to reinitialize a variable if it is guaranteed to be evaluated after the move and before the use. Move The check currently only considers calls of std::move on local vari- ables or function parameters. It does not check moves of member vari- ables or global variables. Any call of std::move on a variable is considered to cause a move of that variable, even if the result of std::move is not passed to an rvalue reference parameter. This means that the check will flag a use-after-move even on a type that does not define a move constructor or move assignment operator. This is intentional. Developers may use std::move on such a type in the expectation that the type will add move semantics in the future. If such a std::move has the potential to cause a use-after-move, we want to warn about it even if the type does not implement move semantics yet. Furthermore, if the result of std::move is passed to an rvalue refer- ence parameter, this will always be considered to cause a move, even if the function that consumes this parameter does not move from it, or if it does so only conditionally. For example, in the following situation, the check will assume that a move always takes place: std::vector<std::string> messages; void f(std::string &&str) { // Only remember the message if it isn't empty. if (!str.empty()) { messages.emplace_back(std::move(str)); } } std::string str = ""; f(std::move(str)); The check will assume that the last line causes a move, even though, in this particular case, it does not. Again, this is intentional. There is one special case: A call to std::move inside a try_emplace call is conservatively assumed not to move. This is to avoid spurious warnings, as the check has no way to reason about the bool returned by try_emplace. When analyzing the order in which moves, uses and reinitializations happen (see section Unsequenced moves, uses, and reinitializations), the move is assumed to occur in whichever function the result of the std::move is passed to. Use Any occurrence of the moved variable that is not a reinitialization (see below) is considered to be a use. An exception to this are objects of type std::unique_ptr, std::shared_ptr and std::weak_ptr, which have defined move behavior (objects of these classes are guaranteed to be empty after they have been moved from). Therefore, an object of these classes will only be considered to be used if it is dereferenced, i.e. if operator*, opera- tor-> or operator[] (in the case of std::unique_ptr<T []>) is called on it. If multiple uses occur after a move, only the first of these is flagged. Reinitialization The check considers a variable to be reinitialized in the following cases: • The variable occurs on the left-hand side of an assignment. • The variable is passed to a function as a non-const pointer or non-const lvalue reference. (It is assumed that the variable may be an out-parameter for the function.) • clear() or assign() is called on the variable and the variable is of one of the standard container types basic_string, vector, deque, forward_list, list, set, map, multiset, multimap, un- ordered_set, unordered_map, unordered_multiset, unordered_mul- timap. • reset() is called on the variable and the variable is of type std::unique_ptr, std::shared_ptr or std::weak_ptr. • A member function marked with the [[clang::reinitializes]] at- tribute is called on the variable. If the variable in question is a struct and an individual member vari- able of that struct is written to, the check does not consider this to be a reinitialization -- even if, eventually, all member variables of the struct are written to. For example: struct S { std::string str; int i; }; S s = { "Hello, world!\n", 42 }; S s_other = std::move(s); s.str = "Lorem ipsum"; s.i = 99; The check will not consider s to be reinitialized after the last line; instead, the line that assigns to s.str will be flagged as a use-af- ter-move. This is intentional as this pattern of reinitializing a struct is error-prone. For example, if an additional member variable is added to S, it is easy to forget to add the reinitialization for this additional member. Instead, it is safer to assign to the entire struct in one go, and this will also avoid the use-after-move warning. bugprone-virtual-near-miss Warn if a function is a near miss (i.e. the name is very similar and the function signature is the same) to a virtual function from a base class. Example: struct Base { virtual void func(); }; struct Derived : Base { virtual void funk(); // warning: 'Derived::funk' has a similar name and the same signature as virtual method 'Base::func'; did you mean to override it? }; cert-con36-c The cert-con36-c check is an alias, please see bugprone-spuriously-wake-up-functions for more information. cert-con54-cpp The cert-con54-cpp check is an alias, please see bugprone-spuriously-wake-up-functions for more information. cert-dcl03-c The cert-dcl03-c check is an alias, please see misc-static-assert for more information. cert-dcl16-c The cert-dcl16-c check is an alias, please see readability-uppercase-literal-suffix for more information. cert-dcl21-cpp NOTE: This check is deprecated since it's no longer part of the CERT stan- dard. It will be removed in clang-tidy version 19. This check flags postfix operator++ and operator-- declarations if the return type is not a const object. This also warns if the return type is a reference type. The object returned by a postfix increment or decrement operator is supposed to be a snapshot of the object's value prior to modification. With such an implementation, any modifications made to the resulting object from calling operator++(int) would be modifying a temporary ob- ject. Thus, such an implementation of a postfix increment or decrement operator should instead return a const object, prohibiting accidental mutation of a temporary object. Similarly, it is unexpected for the postfix operator to return a reference to its previous state, and any subsequent modifications would be operating on a stale object. This check corresponds to the CERT C++ Coding Standard recommendation DCL21-CPP. Overloaded postfix increment and decrement operators should return a const object. However, all of the CERT recommendations have been removed from public view, and so their justification for the be- havior of this check requires an account on their wiki to view. cert-dcl37-c The cert-dcl37-c check is an alias, please see bugprone-reserved-identifier for more information. cert-dcl50-cpp This check flags all function definitions (but not declarations) of C-style variadic functions. This check corresponds to the CERT C++ Coding Standard rule DCL50-CPP. Do not define a C-style variadic function. cert-dcl51-cpp The cert-dcl51-cpp check is an alias, please see bugprone-reserved-identifier for more information. cert-dcl54-cpp The cert-dcl54-cpp check is an alias, please see misc-new-delete-overloads for more information. cert-dcl58-cpp Modification of the std or posix namespace can result in undefined be- havior. This check warns for such modifications. The std (or posix) namespace is allowed to be extended with (class or function) template specializations that depend on an user-defined type (a type that is not defined in the standard system headers). The check detects the following (user provided) declarations in name- space std or posix: • Anything that is not a template specialization. • Explicit specializations of any standard library function template or class template, if it does not have any user-defined type as template argument. • Explicit specializations of any member function of a standard library class template. • Explicit specializations of any member function template of a stan- dard library class or class template. • Explicit or partial specialization of any member class template of a standard library class or class template. Examples: namespace std { int x; // warning: modification of 'std' namespace can result in undefined behavior [cert-dcl58-cpp] } namespace posix::a { // warning: modification of 'posix' namespace can result in undefined behavior } template <> struct ::std::hash<long> { // warning: modification of 'std' namespace can result in undefined behavior unsigned long operator()(const long &K) const { return K; } }; struct MyData { long data; }; template <> struct ::std::hash<MyData> { // no warning: specialization with user-defined type unsigned long operator()(const MyData &K) const { return K.data; } }; namespace std { template <> void swap<bool>(bool &a, bool &b); // warning: modification of 'std' namespace can result in undefined behavior template <> bool less<void>::operator()<MyData &&, MyData &&>(MyData &&, MyData &&) const { // warning: modification of 'std' namespace can result in undefined behavior return true; } } This check corresponds to the CERT C++ Coding Standard rule DCL58-CPP. Do not modify the standard namespaces. cert-dcl59-cpp The cert-dcl59-cpp check is an alias, please see google-build-namespaces for more information. cert-env33-c This check flags calls to system(), popen(), and _popen(), which exe- cute a command processor. It does not flag calls to system() with a null pointer argument, as such a call checks for the presence of a com- mand processor but does not actually attempt to execute a command. This check corresponds to the CERT C Coding Standard rule ENV33-C. Do not call system(). cert-err09-cpp The cert-err09-cpp check is an alias, please see misc-throw-by-value-catch-by-reference for more information. This check corresponds to the CERT C++ Coding Standard recommendation ERR09-CPP. Throw anonymous temporaries. However, all of the CERT recom- mendations have been removed from public view, and so their justifica- tion for the behavior of this check requires an account on their wiki to view. cert-err33-c Warns on unused function return values. Many of the standard library functions return a value that indicates if the call was successful. Ig- noring the returned value can cause unexpected behavior if an error has occurred. The following functions are checked: • aligned_alloc() • asctime_s() • at_quick_exit() • atexit() • bsearch() • bsearch_s() • btowc() • c16rtomb() • c32rtomb() • calloc() • clock() • cnd_broadcast() • cnd_init() • cnd_signal() • cnd_timedwait() • cnd_wait() • ctime_s() • fclose() • fflush() • fgetc() • fgetpos() • fgets() • fgetwc() • fopen() • fopen_s() • fprintf() • fprintf_s() • fputc() • fputs() • fputwc() • fputws() • fread() • freopen() • freopen_s() • fscanf() • fscanf_s() • fseek() • fsetpos() • ftell() • fwprintf() • fwprintf_s() • fwrite() • fwscanf() • fwscanf_s() • getc() • getchar() • getenv() • getenv_s() • gets_s() • getwc() • getwchar() • gmtime() • gmtime_s() • localtime() • localtime_s() • malloc() • mbrtoc16() • mbrtoc32() • mbsrtowcs() • mbsrtowcs_s() • mbstowcs() • mbstowcs_s() • memchr() • mktime() • mtx_init() • mtx_lock() • mtx_timedlock() • mtx_trylock() • mtx_unlock() • printf_s() • putc() • putwc() • raise() • realloc() • remove() • rename() • setlocale() • setvbuf() • scanf() • scanf_s() • signal() • snprintf() • snprintf_s() • sprintf() • sprintf_s() • sscanf() • sscanf_s() • strchr() • strerror_s() • strftime() • strpbrk() • strrchr() • strstr() • strtod() • strtof() • strtoimax() • strtok() • strtok_s() • strtol() • strtold() • strtoll() • strtoumax() • strtoul() • strtoull() • strxfrm() • swprintf() • swprintf_s() • swscanf() • swscanf_s() • thrd_create() • thrd_detach() • thrd_join() • thrd_sleep() • time() • timespec_get() • tmpfile() • tmpfile_s() • tmpnam() • tmpnam_s() • tss_create() • tss_get() • tss_set() • ungetc() • ungetwc() • vfprintf() • vfprintf_s() • vfscanf() • vfscanf_s() • vfwprintf() • vfwprintf_s() • vfwscanf() • vfwscanf_s() • vprintf_s() • vscanf() • vscanf_s() • vsnprintf() • vsnprintf_s() • vsprintf() • vsprintf_s() • vsscanf() • vsscanf_s() • vswprintf() • vswprintf_s() • vswscanf() • vswscanf_s() • vwprintf_s() • vwscanf() • vwscanf_s() • wcrtomb() • wcschr() • wcsftime() • wcspbrk() • wcsrchr() • wcsrtombs() • wcsrtombs_s() • wcsstr() • wcstod() • wcstof() • wcstoimax() • wcstok() • wcstok_s() • wcstol() • wcstold() • wcstoll() • wcstombs() • wcstombs_s() • wcstoumax() • wcstoul() • wcstoull() • wcsxfrm() • wctob() • wctrans() • wctype() • wmemchr() • wprintf_s() • wscanf() • wscanf_s() This check is an alias of check bugprone-unused-return-value with a fixed set of functions. Suppressing issues by casting to void is enabled by default and can be disabled by setting AllowCastToVoid option to false. The check corresponds to a part of CERT C Coding Standard rule ERR33-C. Detect and handle standard library errors. The list of checked func- tions is taken from the rule, with following exception: • The check can not differentiate if a function is called with NULL ar- gument. Therefore the following functions are not checked: mblen, mbrlen, mbrtowc, mbtowc, wctomb, wctomb_s cert-err34-c This check flags calls to string-to-number conversion functions that do not verify the validity of the conversion, such as atoi() or scanf(). It does not flag calls to strtol(), or other, related conversion func- tions that do perform better error checking. #include <stdlib.h> void func(const char *buff) { int si; if (buff) { si = atoi(buff); /* 'atoi' used to convert a string to an integer, but function will not report conversion errors; consider using 'strtol' instead. */ } else { /* Handle error */ } } This check corresponds to the CERT C Coding Standard rule ERR34-C. De- tect errors when converting a string to a number. cert-err52-cpp This check flags all call expressions involving setjmp() and longjmp(). This check corresponds to the CERT C++ Coding Standard rule ERR52-CPP. Do not use setjmp() or longjmp(). cert-err58-cpp This check flags all static or thread_local variable declarations where the initializer for the object may throw an exception. This check corresponds to the CERT C++ Coding Standard rule ERR58-CPP. Handle all exceptions thrown before main() begins executing. cert-err60-cpp This check flags all throw expressions where the exception object is not nothrow copy constructible. This check corresponds to the CERT C++ Coding Standard rule ERR60-CPP. Exception objects must be nothrow copy constructible. cert-err61-cpp The cert-err61-cpp check is an alias, please see misc-throw-by-value-catch-by-reference for more information. cert-exp42-c The cert-exp42-c check is an alias, please see bugprone-suspicious-memory-comparison for more information. cert-fio38-c The cert-fio38-c check is an alias, please see misc-non-copyable-objects for more information. cert-flp30-c This check flags for loops where the induction expression has a float- ing-point type. This check corresponds to the CERT C Coding Standard rule FLP30-C. Do not use floating-point variables as loop counters. cert-flp37-c The cert-flp37-c check is an alias, please see bugprone-suspicious-memory-comparison for more information. cert-mem57-cpp This check flags uses of default operator new where the type has ex- tended alignment (an alignment greater than the fundamental alignment). (The default operator new is guaranteed to provide the correct align- ment if the requested alignment is less or equal to the fundamental alignment). Only cases are detected (by design) where the operator new is not user-defined and is not a placement new (the reason is that in these cases we assume that the user provided the correct memory alloca- tion). This check corresponds to the CERT C++ Coding Standard rule MEM57-CPP. Avoid using default operator new for over-aligned types. cert-msc24-c The cert-msc24-c check is an alias, please see bugprone-unsafe-functions for more information. cert-msc30-c The cert-msc30-c check is an alias, please see cert-msc50-cpp for more information. cert-msc32-c The cert-msc32-c check is an alias, please see cert-msc51-cpp for more information. cert-msc33-c The cert-msc33-c check is an alias, please see bugprone-unsafe-functions for more information. cert-msc50-cpp Pseudorandom number generators use mathematical algorithms to produce a sequence of numbers with good statistical properties, but the numbers produced are not genuinely random. The std::rand() function takes a seed (number), runs a mathematical operation on it and returns the re- sult. By manipulating the seed the result can be predictable. This check warns for the usage of std::rand(). cert-msc51-cpp This check flags all pseudo-random number engines, engine adaptor in- stantiations and srand() when initialized or seeded with default argu- ment, constant expression or any user-configurable type. Pseudo-random number engines seeded with a predictable value may cause vulnerabili- ties e.g. in security protocols. This is a CERT security rule, see MSC51-CPP. Ensure your random number generator is properly seeded and MSC32-C. Properly seed pseudorandom number generators. Examples: void foo() { std::mt19937 engine1; // Diagnose, always generate the same sequence std::mt19937 engine2(1); // Diagnose engine1.seed(); // Diagnose engine2.seed(1); // Diagnose std::time_t t; engine1.seed(std::time(&t)); // Diagnose, system time might be controlled by user int x = atoi(argv[1]); std::mt19937 engine3(x); // Will not warn } Options DisallowedSeedTypes A comma-separated list of the type names which are disallowed. Default values are time_t, std::time_t. cert-msc54-cpp The cert-msc54-cpp check is an alias, please see bugprone-signal-handler for more information. cert-oop11-cpp The cert-oop11-cpp check is an alias, please see performance-move-constructor-init for more information. This check corresponds to the CERT C++ Coding Standard recommendation OOP11-CPP. Do not copy-initialize members or base classes from a move constructor. However, all of the CERT recommendations have been removed from public view, and so their justification for the behavior of this check requires an account on their wiki to view. cert-oop54-cpp The cert-oop54-cpp check is an alias, please see bugprone-unhandled-self-assignment for more information. cert-oop57-cpp Flags use of the C standard library functions memset, memcpy and memcmp and similar derivatives on non-trivial types. Options MemSetNames Specify extra functions to flag that act similarly to memset. Specify names in a semicolon delimited list. Default is an empty string. The check will detect the following functions: memset, std::memset. MemCpyNames Specify extra functions to flag that act similarly to memcpy. Specify names in a semicolon delimited list. Default is an empty string. The check will detect the following functions: std::memcpy, memcpy, std::memmove, memmove, std::strcpy, strcpy, memccpy, stpncpy, strncpy. MemCmpNames Specify extra functions to flag that act similarly to memcmp. Specify names in a semicolon delimited list. Default is an empty string. The check will detect the following functions: std::memcmp, memcmp, std::strcmp, strcmp, strncmp. This check corresponds to the CERT C++ Coding Standard rule OOP57-CPP. Prefer special member functions and overloaded operators to C Standard Library functions. cert-oop58-cpp Finds assignments to the copied object and its direct or indirect mem- bers in copy constructors and copy assignment operators. This check corresponds to the CERT C Coding Standard rule OOP58-CPP. Copy operations must not mutate the source object. cert-pos44-c The cert-pos44-c check is an alias, please see bugprone-bad-signal-to-kill-thread for more information. cert-pos47-c The cert-pos47-c check is an alias, please see concurrency-thread-canceltype-asynchronous for more information. cert-sig30-c The cert-sig30-c check is an alias, please see bugprone-signal-handler for more information. cert-str34-c The cert-str34-c check is an alias, please see bugprone-signed-char-misuse for more information. clang-analyzer-core.BitwiseShift Finds cases where bitwise shift operation causes undefined behaviour. The clang-analyzer-core.BitwiseShift check is an alias, please see Clang Static Analyzer Available Checkers for more information. clang-analyzer-core.CallAndMessage Check for logical errors for function calls and Objective-C message ex- pressions (e.g., uninitialized arguments, null function pointers). The clang-analyzer-core.CallAndMessage check is an alias, please see Clang Static Analyzer Available Checkers for more information. clang-analyzer-core.DivideZero Check for division by zero. The clang-analyzer-core.DivideZero check is an alias, please see Clang Static Analyzer Available Checkers for more information. clang-analyzer-core.NonNullParamChecker Check for null pointers passed as arguments to a function whose argu- ments are references or marked with the 'nonnull' attribute. The clang-analyzer-core.NonNullParamChecker check is an alias, please see Clang Static Analyzer Available Checkers for more information. clang-analyzer-core.NullDereference Check for dereferences of null pointers. The clang-analyzer-core.NullDereference check is an alias, please see Clang Static Analyzer Available Checkers for more information. clang-analyzer-core.StackAddressEscape Check that addresses to stack memory do not escape the function. The clang-analyzer-core.StackAddressEscape check is an alias, please see Clang Static Analyzer Available Checkers for more information. clang-analyzer-core.UndefinedBinaryOperatorResult Check for undefined results of binary operators. The clang-analyzer-core.UndefinedBinaryOperatorResult check is an alias, please see Clang Static Analyzer Available Checkers for more in- formation. clang-analyzer-core.VLASize Check for declarations of VLA of undefined or zero size. The clang-analyzer-core.VLASize check is an alias, please see Clang Static Analyzer Available Checkers for more information. clang-analyzer-core.uninitialized.ArraySubscript Check for uninitialized values used as array subscripts. The clang-analyzer-core.uninitialized.ArraySubscript check is an alias, please see Clang Static Analyzer Available Checkers for more informa- tion. clang-analyzer-core.uninitialized.Assign Check for assigning uninitialized values. The clang-analyzer-core.uninitialized.Assign check is an alias, please see Clang Static Analyzer Available Checkers for more information. clang-analyzer-core.uninitialized.Branch Check for uninitialized values used as branch conditions. The clang-analyzer-core.uninitialized.Branch check is an alias, please see Clang Static Analyzer Available Checkers for more information. clang-analyzer-core.uninitialized.CapturedBlockVariable Check for blocks that capture uninitialized values. The clang-analyzer-core.uninitialized.CapturedBlockVariable check is an alias, please see Clang Static Analyzer Available Checkers for more in- formation. clang-analyzer-core.uninitialized.NewArraySize Check if the size of the array in a new[] expression is undefined. The clang-analyzer-core.uninitialized.NewArraySize check is an alias, please see Clang Static Analyzer Available Checkers for more informa- tion. clang-analyzer-core.uninitialized.UndefReturn Check for uninitialized values being returned to the caller. The clang-analyzer-core.uninitialized.UndefReturn check is an alias, please see Clang Static Analyzer Available Checkers for more informa- tion. clang-analyzer-cplusplus.InnerPointer Check for inner pointers of C++ containers used after re/deallocation. The clang-analyzer-cplusplus.InnerPointer check is an alias, please see Clang Static Analyzer Available Checkers for more information. clang-analyzer-cplusplus.Move Find use-after-move bugs in C++. The clang-analyzer-cplusplus.Move check is an alias of Clang Static An- alyzer cplusplus.Move. clang-analyzer-cplusplus.NewDelete Check for double-free and use-after-free problems. Traces memory man- aged by new/delete. The clang-analyzer-cplusplus.NewDelete check is an alias, please see Clang Static Analyzer Available Checkers for more information. clang-analyzer-cplusplus.NewDeleteLeaks Check for memory leaks. Traces memory managed by new/delete. The clang-analyzer-cplusplus.NewDeleteLeaks check is an alias, please see Clang Static Analyzer Available Checkers for more information. clang-analyzer-cplusplus.PlacementNew Check if default placement new is provided with pointers to sufficient storage capacity. The clang-analyzer-cplusplus.PlacementNew check is an alias, please see Clang Static Analyzer Available Checkers for more information. clang-analyzer-cplusplus.PureVirtualCall Check pure virtual function calls during construction/destruction. The clang-analyzer-cplusplus.PureVirtualCall check is an alias of Clang Static Analyzer cplusplus.PureVirtualCall. clang-analyzer-cplusplus.StringChecker Checks C++ std::string bugs. The clang-analyzer-cplusplus.StringChecker check is an alias, please see Clang Static Analyzer Available Checkers for more information. clang-analyzer-deadcode.DeadStores Check for values stored to variables that are never read afterwards. The clang-analyzer-deadcode.DeadStores check is an alias, please see Clang Static Analyzer Available Checkers for more information. clang-analyzer-fuchsia.HandleChecker A Checker that detect leaks related to Fuchsia handles. The clang-analyzer-fuchsia.HandleChecker check is an alias, please see Clang Static Analyzer Available Checkers for more information. clang-analyzer-nullability.NullPassedToNonnull Warns when a null pointer is passed to a pointer which has a _Nonnull type. The clang-analyzer-nullability.NullPassedToNonnull check is an alias, please see Clang Static Analyzer Available Checkers for more informa- tion. clang-analyzer-nullability.NullReturnedFromNonnull Warns when a null pointer is returned from a function that has _Nonnull return type. The clang-analyzer-nullability.NullReturnedFromNonnull check is an alias, please see Clang Static Analyzer Available Checkers for more in- formation. clang-analyzer-nullability.NullableDereferenced Warns when a nullable pointer is dereferenced. The clang-analyzer-nullability.NullableDereferenced check is an alias, please see Clang Static Analyzer Available Checkers for more informa- tion. clang-analyzer-nullability.NullablePassedToNonnull Warns when a nullable pointer is passed to a pointer which has a _Non- null type. The clang-analyzer-nullability.NullablePassedToNonnull check is an alias, please see Clang Static Analyzer Available Checkers for more in- formation. clang-analyzer-nullability.NullableReturnedFromNonnull Warns when a nullable pointer is returned from a function that has _Nonnull return type. The clang-analyzer-nullability.NullableReturnedFromNonnull check is an alias, please see Clang Static Analyzer Available Checkers for more in- formation. clang-analyzer-optin.core.EnumCastOutOfRange Check integer to enumeration casts for out of range values. The clang-analyzer-optin.core.EnumCastOutOfRange check is an alias, please see Clang Static Analyzer Available Checkers for more informa- tion. clang-analyzer-optin.cplusplus.UninitializedObject Reports uninitialized fields after object construction. The clang-analyzer-optin.cplusplus.UninitializedObject check is an alias, please see Clang Static Analyzer Available Checkers for more in- formation. clang-analyzer-optin.cplusplus.VirtualCall Check virtual function calls during construction/destruction. The clang-analyzer-optin.cplusplus.VirtualCall check is an alias, please see Clang Static Analyzer Available Checkers for more informa- tion. clang-analyzer-optin.mpi.MPI-Checker Checks MPI code. The clang-analyzer-optin.mpi.MPI-Checker check is an alias, please see Clang Static Analyzer Available Checkers for more information. clang-analyzer-optin.osx.OSObjectCStyleCast Checker for C-style casts of OSObjects. The clang-analyzer-optin.osx.OSObjectCStyleCast check is an alias of Clang Static Analyzer optin.osx.OSObjectCStyleCast. clang-analyzer-optin.osx.cocoa.localizability.EmptyLocalizationCon- textChecker Check that NSLocalizedString macros include a comment for context. The clang-analyzer-optin.osx.cocoa.localizability.EmptyLocalizationCon- textChecker check is an alias, please see Clang Static Analyzer Avail- able Checkers for more information. clang-analyzer-optin.osx.cocoa.localizability.NonLocalizedStringChecker Warns about uses of non-localized NSStrings passed to UI methods ex- pecting localized NSStrings. The clang-analyzer-optin.osx.cocoa.localizability.NonLocalized- StringChecker check is an alias, please see Clang Static Analyzer Available Checkers for more information. clang-analyzer-optin.performance.GCDAntipattern Check for performance anti-patterns when using Grand Central Dispatch. The clang-analyzer-optin.performance.GCDAntipattern check is an alias, please see Clang Static Analyzer Available Checkers for more informa- tion. clang-analyzer-optin.performance.Padding Check for excessively padded structs. The clang-analyzer-optin.performance.Padding check is an alias, please see Clang Static Analyzer Available Checkers for more information. clang-analyzer-optin.portability.UnixAPI Finds implementation-defined behavior in UNIX/Posix functions. The clang-analyzer-optin.portability.UnixAPI check is an alias, please see Clang Static Analyzer Available Checkers for more information. clang-analyzer-osx.API Check for proper uses of various Apple APIs. The clang-analyzer-osx.API check is an alias, please see Clang Static Analyzer Available Checkers for more information. clang-analyzer-osx.MIG Find violations of the Mach Interface Generator calling convention. The clang-analyzer-osx.MIG check is an alias of Clang Static Analyzer osx.MIG. clang-analyzer-osx.NumberObjectConversion Check for erroneous conversions of objects representing numbers into numbers. The clang-analyzer-osx.NumberObjectConversion check is an alias, please see Clang Static Analyzer Available Checkers for more information. clang-analyzer-osx.OSObjectRetainCount Check for leaks and improper reference count management for OSObject. The clang-analyzer-osx.OSObjectRetainCount check is an alias of Clang Static Analyzer osx.OSObjectRetainCount. clang-analyzer-osx.ObjCProperty Check for proper uses of Objective-C properties. The clang-analyzer-osx.ObjCProperty check is an alias, please see Clang Static Analyzer Available Checkers for more information. clang-analyzer-osx.SecKeychainAPI Check for proper uses of Secure Keychain APIs. The clang-analyzer-osx.SecKeychainAPI check is an alias, please see Clang Static Analyzer Available Checkers for more information. clang-analyzer-osx.cocoa.AtSync Check for nil pointers used as mutexes for @synchronized. The clang-analyzer-osx.cocoa.AtSync check is an alias, please see Clang Static Analyzer Available Checkers for more information. clang-analyzer-osx.cocoa.AutoreleaseWrite Warn about potentially crashing writes to autoreleasing objects from different autoreleasing pools in Objective-C. The clang-analyzer-osx.cocoa.AutoreleaseWrite check is an alias, please see Clang Static Analyzer Available Checkers for more information. clang-analyzer-osx.cocoa.ClassRelease Check for sending 'retain', 'release', or 'autorelease' directly to a Class. The clang-analyzer-osx.cocoa.ClassRelease check is an alias, please see Clang Static Analyzer Available Checkers for more information. clang-analyzer-osx.cocoa.Dealloc Warn about Objective-C classes that lack a correct implementation of -dealloc. The clang-analyzer-osx.cocoa.Dealloc check is an alias, please see Clang Static Analyzer Available Checkers for more information. clang-analyzer-osx.cocoa.IncompatibleMethodTypes Warn about Objective-C method signatures with type incompatibilities. The clang-analyzer-osx.cocoa.IncompatibleMethodTypes check is an alias, please see Clang Static Analyzer Available Checkers for more informa- tion. clang-analyzer-osx.cocoa.Loops Improved modeling of loops using Cocoa collection types. The clang-analyzer-osx.cocoa.Loops check is an alias, please see Clang Static Analyzer Available Checkers for more information. clang-analyzer-osx.cocoa.MissingSuperCall Warn about Objective-C methods that lack a necessary call to super. The clang-analyzer-osx.cocoa.MissingSuperCall check is an alias, please see Clang Static Analyzer Available Checkers for more information. clang-analyzer-osx.cocoa.NSAutoreleasePool Warn for suboptimal uses of NSAutoreleasePool in Objective-C GC mode. The clang-analyzer-osx.cocoa.NSAutoreleasePool check is an alias, please see Clang Static Analyzer Available Checkers for more informa- tion. clang-analyzer-osx.cocoa.NSError Check usage of NSError** parameters. The clang-analyzer-osx.cocoa.NSError check is an alias, please see Clang Static Analyzer Available Checkers for more information. clang-analyzer-osx.cocoa.NilArg Check for prohibited nil arguments to ObjC method calls. The clang-analyzer-osx.cocoa.NilArg check is an alias, please see Clang Static Analyzer Available Checkers for more information. clang-analyzer-osx.cocoa.NonNilReturnValue Model the APIs that are guaranteed to return a non-nil value. The clang-analyzer-osx.cocoa.NonNilReturnValue check is an alias, please see Clang Static Analyzer Available Checkers for more informa- tion. clang-analyzer-osx.cocoa.ObjCGenerics Check for type errors when using Objective-C generics. The clang-analyzer-osx.cocoa.ObjCGenerics check is an alias, please see Clang Static Analyzer Available Checkers for more information. clang-analyzer-osx.cocoa.RetainCount Check for leaks and improper reference count management. The clang-analyzer-osx.cocoa.RetainCount check is an alias, please see Clang Static Analyzer Available Checkers for more information. clang-analyzer-osx.cocoa.RunLoopAutoreleaseLeak Check for leaked memory in autorelease pools that will never be drained. The clang-analyzer-osx.cocoa.RunLoopAutoreleaseLeak check is an alias, please see Clang Static Analyzer Available Checkers for more informa- tion. clang-analyzer-osx.cocoa.SelfInit Check that 'self' is properly initialized inside an initializer method. The clang-analyzer-osx.cocoa.SelfInit check is an alias, please see Clang Static Analyzer Available Checkers for more information. clang-analyzer-osx.cocoa.SuperDealloc Warn about improper use of '[super dealloc]' in Objective-C. The clang-analyzer-osx.cocoa.SuperDealloc check is an alias, please see Clang Static Analyzer Available Checkers for more information. clang-analyzer-osx.cocoa.UnusedIvars Warn about private ivars that are never used. The clang-analyzer-osx.cocoa.UnusedIvars check is an alias, please see Clang Static Analyzer Available Checkers for more information. clang-analyzer-osx.cocoa.VariadicMethodTypes Check for passing non-Objective-C types to variadic collection initial- ization methods that expect only Objective-C types. The clang-analyzer-osx.cocoa.VariadicMethodTypes check is an alias, please see Clang Static Analyzer Available Checkers for more informa- tion. clang-analyzer-osx.coreFoundation.CFError Check usage of CFErrorRef* parameters. The clang-analyzer-osx.coreFoundation.CFError check is an alias, please see Clang Static Analyzer Available Checkers for more information. clang-analyzer-osx.coreFoundation.CFNumber Check for proper uses of CFNumber APIs. The clang-analyzer-osx.coreFoundation.CFNumber check is an alias, please see Clang Static Analyzer Available Checkers for more informa- tion. clang-analyzer-osx.coreFoundation.CFRetainRelease Check for null arguments to CFRetain/CFRelease/CFMakeCollectable. The clang-analyzer-osx.coreFoundation.CFRetainRelease check is an alias, please see Clang Static Analyzer Available Checkers for more in- formation. clang-analyzer-osx.coreFoundation.containers.OutOfBounds Checks for index out-of-bounds when using 'CFArray' API. The clang-analyzer-osx.coreFoundation.containers.OutOfBounds check is an alias, please see Clang Static Analyzer Available Checkers for more information. clang-analyzer-osx.coreFoundation.containers.PointerSizedValues Warns if 'CFArray', 'CFDictionary', 'CFSet' are created with non-pointer-size values. The clang-analyzer-osx.coreFoundation.containers.PointerSizedValues check is an alias, please see Clang Static Analyzer Available Checkers for more information. clang-analyzer-security.FloatLoopCounter Warn on using a floating point value as a loop counter (CERT: FLP30-C, FLP30-CPP). The clang-analyzer-security.FloatLoopCounter check is an alias, please see Clang Static Analyzer Available Checkers for more information. clang-analyzer-security.cert.env.InvalidPtr Finds usages of possibly invalidated pointers. The clang-analyzer-security.cert.env.InvalidPtr check is an alias, please see Clang Static Analyzer Available Checkers for more informa- tion. clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling Warn on uses of unsecure or deprecated buffer manipulating functions. The clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHan- dling check is an alias, please see Clang Static Analyzer Available Checkers for more information. clang-analyzer-security.insecureAPI.UncheckedReturn Warn on uses of functions whose return values must be always checked. The clang-analyzer-security.insecureAPI.UncheckedReturn check is an alias, please see Clang Static Analyzer Available Checkers for more in- formation. clang-analyzer-security.insecureAPI.bcmp Warn on uses of the 'bcmp' function. The clang-analyzer-security.insecureAPI.bcmp check is an alias, please see Clang Static Analyzer Available Checkers for more information. clang-analyzer-security.insecureAPI.bcopy Warn on uses of the 'bcopy' function. The clang-analyzer-security.insecureAPI.bcopy check is an alias, please see Clang Static Analyzer Available Checkers for more information. clang-analyzer-security.insecureAPI.bzero Warn on uses of the 'bzero' function. The clang-analyzer-security.insecureAPI.bzero check is an alias, please see Clang Static Analyzer Available Checkers for more information. clang-analyzer-security.insecureAPI.decodeValueOfObjCType Warn on uses of the '-decodeValueOfObjCType:at:' method. The clang-analyzer-security.insecureAPI.decodeValueOfObjCType check is an alias of Clang Static Analyzer security.insecureAPI.decodeValueOfOb- jCType. clang-analyzer-security.insecureAPI.getpw Warn on uses of the 'getpw' function. The clang-analyzer-security.insecureAPI.getpw check is an alias, please see Clang Static Analyzer Available Checkers for more information. clang-analyzer-security.insecureAPI.gets Warn on uses of the 'gets' function. The clang-analyzer-security.insecureAPI.gets check is an alias, please see Clang Static Analyzer Available Checkers for more information. clang-analyzer-security.insecureAPI.mkstemp Warn when 'mkstemp' is passed fewer than 6 X's in the format string. The clang-analyzer-security.insecureAPI.mkstemp check is an alias, please see Clang Static Analyzer Available Checkers for more informa- tion. clang-analyzer-security.insecureAPI.mktemp Warn on uses of the 'mktemp' function. The clang-analyzer-security.insecureAPI.mktemp check is an alias, please see Clang Static Analyzer Available Checkers for more informa- tion. clang-analyzer-security.insecureAPI.rand Warn on uses of the 'rand', 'random', and related functions. The clang-analyzer-security.insecureAPI.rand check is an alias, please see Clang Static Analyzer Available Checkers for more information. clang-analyzer-security.insecureAPI.strcpy Warn on uses of the 'strcpy' and 'strcat' functions. The clang-analyzer-security.insecureAPI.strcpy check is an alias, please see Clang Static Analyzer Available Checkers for more informa- tion. clang-analyzer-security.insecureAPI.vfork Warn on uses of the 'vfork' function. The clang-analyzer-security.insecureAPI.vfork check is an alias, please see Clang Static Analyzer Available Checkers for more information. clang-analyzer-unix.API Check calls to various UNIX/Posix functions. The clang-analyzer-unix.API check is an alias, please see Clang Static Analyzer Available Checkers for more information. clang-analyzer-unix.Errno Check for improper use of 'errno'. The clang-analyzer-unix.Errno check is an alias, please see Clang Sta- tic Analyzer Available Checkers for more information. clang-analyzer-unix.Malloc Check for memory leaks, double free, and use-after-free problems. Traces memory managed by malloc()/free(). The clang-analyzer-unix.Malloc check is an alias, please see Clang Sta- tic Analyzer Available Checkers for more information. clang-analyzer-unix.MallocSizeof Check for dubious malloc arguments involving sizeof. The clang-analyzer-unix.MallocSizeof check is an alias, please see Clang Static Analyzer Available Checkers for more information. clang-analyzer-unix.MismatchedDeallocator Check for mismatched deallocators. The clang-analyzer-unix.MismatchedDeallocator check is an alias, please see Clang Static Analyzer Available Checkers for more information. clang-analyzer-unix.StdCLibraryFunctions Check for invalid arguments of C standard library functions, and apply relations between arguments and return value. The clang-analyzer-unix.StdCLibraryFunctions check is an alias, please see Clang Static Analyzer Available Checkers for more information. clang-analyzer-unix.Vfork Check for proper usage of vfork. The clang-analyzer-unix.Vfork check is an alias, please see Clang Sta- tic Analyzer Available Checkers for more information. clang-analyzer-unix.cstring.BadSizeArg Check the size argument passed into C string functions for common erro- neous patterns. The clang-analyzer-unix.cstring.BadSizeArg check is an alias, please see Clang Static Analyzer Available Checkers for more information. clang-analyzer-unix.cstring.NullArg Check for null pointers being passed as arguments to C string func- tions. The clang-analyzer-unix.cstring.NullArg check is an alias, please see Clang Static Analyzer Available Checkers for more information. clang-analyzer-valist.CopyToSelf Check for va_lists which are copied onto itself. The clang-analyzer-valist.CopyToSelf check is an alias of Clang Static Analyzer valist.CopyToSelf. clang-analyzer-valist.Uninitialized Check for usages of uninitialized (or already released) va_lists. The clang-analyzer-valist.Uninitialized check is an alias of Clang Sta- tic Analyzer valist.Uninitialized. clang-analyzer-valist.Unterminated Check for va_lists which are not released by a va_end call. The clang-analyzer-valist.Unterminated check is an alias of Clang Sta- tic Analyzer valist.Unterminated. clang-analyzer-webkit.NoUncountedMemberChecker Check for no uncounted member variables. The clang-analyzer-webkit.NoUncountedMemberChecker check is an alias, please see Clang Static Analyzer Available Checkers for more informa- tion. clang-analyzer-webkit.RefCntblBaseVirtualDtor Check for any ref-countable base class having virtual destructor. The clang-analyzer-webkit.RefCntblBaseVirtualDtor check is an alias, please see Clang Static Analyzer Available Checkers for more informa- tion. clang-analyzer-webkit.UncountedLambdaCapturesChecker Check uncounted lambda captures. The clang-analyzer-webkit.UncountedLambdaCapturesChecker check is an alias, please see Clang Static Analyzer Available Checkers for more in- formation. concurrency-mt-unsafe Checks for some thread-unsafe functions against a black list of known-to-be-unsafe functions. Usually they access static variables without synchronization (e.g. gmtime(3)) or utilize signals in a racy way. The set of functions to check is specified with the FunctionSet option. Note that using some thread-unsafe functions may be still valid in con- current programming if only a single thread is used (e.g. setenv(3)), however, some functions may track a state in global variables which would be clobbered by subsequent (non-parallel, but concurrent) calls to a related function. E.g. the following code suffers from unprotected accesses to a global state: // getnetent(3) maintains global state with DB connection, etc. // If a concurrent green thread calls getnetent(3), the global state is corrupted. netent = getnetent(); yield(); netent = getnetent(); Examples: tm = gmtime(timep); // uses a global buffer sleep(1); // implementation may use SIGALRM FunctionSet Specifies which functions in libc should be considered thread-safe, possible values are posix, glibc, or any. posix means POSIX defined thread-unsafe functions. POSIX.1-2001 in "2.9.1 Thread-Safety" defines that all functions specified in the standard are thread-safe except a predefined list of thread-unsafe functions. Glibc defines some of them as thread-safe (e.g. dirname(3)), but adds non-POSIX thread-unsafe ones (e.g. getopt_long(3)). Glibc's list is compiled from GNU web documentation with a search for MT-Safe tag: https://www.gnu.org/software/libc/manual/html_node/POSIX-Safety-Concepts.html If you want to identify thread-unsafe API for at least one libc or unsure which libc will be used, use any (default). concurrency-thread-canceltype-asynchronous Finds pthread_setcanceltype function calls where a thread's cancella- tion type is set to asynchronous. Asynchronous cancellation type (PTHREAD_CANCEL_ASYNCHRONOUS) is generally unsafe, use type PTHREAD_CANCEL_DEFERRED instead which is the default. Even with de- ferred cancellation, a cancellation point in an asynchronous signal handler may still be acted upon and the effect is as if it was an asyn- chronous cancellation. pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldtype); This check corresponds to the CERT C Coding Standard rule POS47-C. Do not use threads that can be canceled asynchronously. cppcoreguidelines-avoid-c-arrays The cppcoreguidelines-avoid-c-arrays check is an alias, please see modernize-avoid-c-arrays for more information. cppcoreguidelines-avoid-capturing-lambda-coroutines Flags C++20 coroutine lambdas with non-empty capture lists that may cause use-after-free errors and suggests avoiding captures or ensuring the lambda closure object has a guaranteed lifetime. This check implements CP.51 from the C++ Core Guidelines. Using coroutine lambdas with non-empty capture lists can be risky, as capturing variables can lead to accessing freed memory after the first suspension point. This issue can occur even with refcounted smart pointers and copyable types. When a lambda expression creates a corou- tine, it results in a closure object with storage, which is often on the stack and will eventually go out of scope. When the closure object goes out of scope, its captures also go out of scope. While normal lambdas finish executing before this happens, coroutine lambdas may re- sume from suspension after the closure object has been destructed, re- sulting in use-after-free memory access for all captures. Consider the following example: int value = get_value(); std::shared_ptr<Foo> sharedFoo = get_foo(); { const auto lambda = [value, sharedFoo]() -> std::future<void> { co_await something(); // "sharedFoo" and "value" have already been destroyed // the "shared" pointer didn't accomplish anything }; lambda(); } // the lambda closure object has now gone out of scope In this example, the lambda object is defined with two captures: value and sharedFoo. When lambda() is called, the lambda object is created on the stack, and the captures are copied into the closure object. When the coroutine is suspended, the lambda object goes out of scope, and the closure object is destroyed. When the coroutine is resumed, the captured variables may have been destroyed, resulting in use-after-free bugs. In conclusion, the use of coroutine lambdas with non-empty capture lists can lead to use-after-free errors when resuming the coroutine af- ter the closure object has been destroyed. This check helps prevent such errors by flagging C++20 coroutine lambdas with non-empty capture lists and suggesting avoiding captures or ensuring the lambda closure object has a guaranteed lifetime. Following these guidelines can help ensure the safe and reliable use of coroutine lambdas in C++ code. cppcoreguidelines-avoid-const-or-ref-data-members This check warns when structs or classes that are copyable or movable, and have const-qualified or reference (lvalue or rvalue) data members. Having such members is rarely useful, and makes the class only copy-constructible but not copy-assignable. Examples: // Bad, const-qualified member struct Const { const int x; } // Good: class Foo { public: int get() const { return x; } private: int x; }; // Bad, lvalue reference member struct Ref { int& x; }; // Good: struct Foo { int* x; std::unique_ptr<int> x; std::shared_ptr<int> x; gsl::not_null<int> x; }; // Bad, rvalue reference member struct RefRef { int&& x; }; This check implements C.12 from the C++ Core Guidelines. Further reading: Data members: Never const. cppcoreguidelines-avoid-do-while Warns when using do-while loops. They are less readable than plain while loops, since the termination condition is at the end and the con- dition is not checked prior to the first iteration. This can lead to subtle bugs. This check implements ES.75 from the C++ Core Guidelines. Examples: int x; do { std::cin >> x; // ... } while (x < 0); Options IgnoreMacros Ignore the check when analyzing macros. This is useful for safely defining function-like macros: #define FOO_BAR(x) \ do { \ foo(x); \ bar(x); \ } while(0) Defaults to false. cppcoreguidelines-avoid-goto The usage of goto for control flow is error prone and should be re- placed with looping constructs. Only forward jumps in nested loops are accepted. This check implements ES.76 from the C++ Core Guidelines and 6.3.1 from High Integrity C++ Coding Standard. For more information on why to avoid programming with goto you can read the famous paper A Case against the GO TO Statement.. The check diagnoses goto for backward jumps in every language mode. These should be replaced with C/C++ looping constructs. // Bad, handwritten for loop. int i = 0; // Jump label for the loop loop_start: do_some_operation(); if (i < 100) { ++i; goto loop_start; } // Better for(int i = 0; i < 100; ++i) do_some_operation(); Modern C++ needs goto only to jump out of nested loops. for(int i = 0; i < 100; ++i) { for(int j = 0; j < 100; ++j) { if (i * j > 500) goto early_exit; } } early_exit: some_operation(); All other uses of goto are diagnosed in C++. cppcoreguidelines-avoid-magic-numbers The cppcoreguidelines-avoid-magic-numbers check is an alias, please see readability-magic-numbers for more information. cppcoreguidelines-avoid-non-const-global-variables Finds non-const global variables as described in I.2 of C++ Core Guide- lines. As R.6 of C++ Core Guidelines is a duplicate of rule I.2 it also covers that rule. char a; // Warns! const char b = 0; namespace some_namespace { char c; // Warns! const char d = 0; } char * c_ptr1 = &some_namespace::c; // Warns! char *const c_const_ptr = &some_namespace::c; // Warns! char & c_reference = some_namespace::c; // Warns! class Foo // No Warnings inside Foo, only namespace scope is covered { public: char e = 0; const char f = 0; protected: char g = 0; private: char h = 0; }; The variables a, c, c_ptr1, c_const_ptr and c_reference will all gener- ate warnings since they are either a non-const globally accessible variable, a pointer or a reference providing global access to non-const data or both. cppcoreguidelines-avoid-reference-coroutine-parameters Warns when a coroutine accepts reference parameters. After a coroutine suspend point, references could be dangling and no longer valid. In- stead, pass parameters as values. Examples: std::future<int> someCoroutine(int& val) { co_await ...; // When the coroutine is resumed, 'val' might no longer be valid. if (val) ... } This check implements CP.53 from the C++ Core Guidelines. cppcoreguidelines-c-copy-assignment-signature The cppcoreguidelines-c-copy-assignment-signature check is an alias, please see misc-unconventional-assign-operator for more information. cppcoreguidelines-explicit-virtual-functions The cppcoreguidelines-explicit-virtual-functions check is an alias, please see modernize-use-override for more information. cppcoreguidelines-init-variables Checks whether there are local variables that are declared without an initial value. These may lead to unexpected behavior if there is a code path that reads the variable before assigning to it. This rule is part of the Type safety (Type.5) profile and ES.20 from the C++ Core Guidelines. Only integers, booleans, floats, doubles and pointers are checked. The fix option initializes all detected values with the value of zero. An exception is float and double types, which are initialized to NaN. As an example a function that looks like this: void function() { int x; char *txt; double d; // Rest of the function. } Would be rewritten to look like this: #include <math.h> void function() { int x = 0; char *txt = nullptr; double d = NAN; // Rest of the function. } It warns for the uninitialized enum case, but without a FixIt: enum A {A1, A2, A3}; enum A_c : char { A_c1, A_c2, A_c3 }; enum class B { B1, B2, B3 }; enum class B_i : int { B_i1, B_i2, B_i3 }; void function() { A a; // Warning: variable 'a' is not initialized A_c a_c; // Warning: variable 'a_c' is not initialized B b; // Warning: variable 'b' is not initialized B_i b_i; // Warning: variable 'b_i' is not initialized } Options IncludeStyle A string specifying which include-style is used, llvm or google. Default is llvm. MathHeader A string specifying the header to include to get the definition of NAN. Default is <math.h>. cppcoreguidelines-interfaces-global-init This check flags initializers of globals that access extern objects, and therefore can lead to order-of-initialization problems. This check implements I.22 from the C++ Core Guidelines. Note that currently this does not flag calls to non-constexpr func- tions, and therefore globals could still be accessed from functions themselves. cppcoreguidelines-macro-to-enum The cppcoreguidelines-macro-to-enum check is an alias, please see modernize-macro-to-enum for more information. cppcoreguidelines-macro-usage Finds macro usage that is considered problematic because better lan- guage constructs exist for the task. The relevant sections in the C++ Core Guidelines are ES.31, and ES.32. Examples: #define C 0 #define F1(x, y) ((a) > (b) ? (a) : (b)) #define F2(...) (__VA_ARGS__) #define COMMA , #define NORETURN [[noreturn]] #define DEPRECATED attribute((deprecated)) #if LIB_EXPORTS #define DLLEXPORTS __declspec(dllexport) #else #define DLLEXPORTS __declspec(dllimport) #endif results in the following warnings: 4 warnings generated. test.cpp:1:9: warning: macro 'C' used to declare a constant; consider using a 'constexpr' constant [cppcoreguidelines-macro-usage] #define C 0 ^ test.cpp:2:9: warning: function-like macro 'F1' used; consider a 'constexpr' template function [cppcoreguidelines-macro-usage] #define F1(x, y) ((a) > (b) ? (a) : (b)) ^ test.cpp:3:9: warning: variadic macro 'F2' used; consider using a 'constexpr' variadic template function [cppcoreguidelines-macro-usage] #define F2(...) (__VA_ARGS__) ^ Options AllowedRegexp A regular expression to filter allowed macros. For example DE- BUG*|LIBTORRENT*|TORRENT*|UNI* could be applied to filter libtorrent. Default value is ^DEBUG_*. CheckCapsOnly Boolean flag to warn on all macros except those with CAPS_ONLY names. This option is intended to ease introduction of this check into older code bases. Default value is false. IgnoreCommandLineMacros Boolean flag to toggle ignoring command-line-defined macros. Default value is true. cppcoreguidelines-misleading-capture-default-by-value Warns when lambda specify a by-value capture default and capture this. By-value capture defaults in member functions can be misleading about whether data members are captured by value or reference. This occurs because specifying the capture default [=] actually captures the this pointer by value, not the data members themselves. As a result, data members are still indirectly accessed via the captured this pointer, which essentially means they are being accessed by reference. There- fore, even when using [=], data members are effectively captured by reference, which might not align with the user's expectations. Examples: struct AClass { int member; void misleadingLogic() { int local = 0; member = 0; auto f = [=]() mutable { local += 1; member += 1; }; f(); // Here, local is 0 but member is 1 } void clearLogic() { int local = 0; member = 0; auto f = [this, local]() mutable { local += 1; member += 1; }; f(); // Here, local is 0 but member is 1 } }; This check implements F.54 from the C++ Core Guidelines. cppcoreguidelines-missing-std-forward Warns when a forwarding reference parameter is not forwarded inside the function body. Example: template <class T> void wrapper(T&& t) { impl(std::forward<T>(t), 1, 2); // Correct } template <class T> void wrapper2(T&& t) { impl(t, 1, 2); // Oops - should use std::forward<T>(t) } template <class T> void wrapper3(T&& t) { impl(std::move(t), 1, 2); // Also buggy - should use std::forward<T>(t) } template <class F> void wrapper_function(F&& f) { std::forward<F>(f)(1, 2); // Correct } template <class F> void wrapper_function2(F&& f) { f(1, 2); // Incorrect - may not invoke the desired qualified function operator } This check implements F.19 from the C++ Core Guidelines. cppcoreguidelines-narrowing-conversions Checks for silent narrowing conversions, e.g: int i = 0; i += 0.1;. While the issue is obvious in this former example, it might not be so in the following: void MyClass::f(double d) { int_member_ += d; }. This check implements ES.46 from the C++ Core Guidelines. We enforce only part of the guideline, more specifically, we flag nar- rowing conversions from: • an integer to a narrower integer (e.g. char to unsigned char) if WarnOnIntegerNarrowingConversion Option is set, • an integer to a narrower floating-point (e.g. uint64_t to float) if WarnOnIntegerToFloatingPointNarrowingConversion Op- tion is set, • a floating-point to an integer (e.g. double to int), • a floating-point to a narrower floating-point (e.g. double to float) if WarnOnFloatingPointNarrowingConversion Option is set. This check will flag: • All narrowing conversions that are not marked by an explicit cast (c-style or static_cast). For example: int i = 0; i += 0.1;, void f(int); f(0.1);, • All applications of binary operators with a narrowing conver- sions. For example: int i; i+= 0.1;. Options WarnOnIntegerNarrowingConversion When true, the check will warn on narrowing integer conversion (e.g. int to size_t). true by default. WarnOnIntegerToFloatingPointNarrowingConversion When true, the check will warn on narrowing integer to float- ing-point conversion (e.g. size_t to double). true by default. WarnOnFloatingPointNarrowingConversion When true, the check will warn on narrowing floating point con- version (e.g. double to float). true by default. WarnWithinTemplateInstantiation When true, the check will warn on narrowing conversions within template instantiations. false by default. WarnOnEquivalentBitWidth When true, the check will warn on narrowing conversions that arise from casting between types of equivalent bit width. (e.g. int n = uint(0); or long long n = double(0);) true by default. IgnoreConversionFromTypes Narrowing conversions from any type in this semicolon-separated list will be ignored. This may be useful to weed out commonly occurring, but less commonly problematic assignments such as int n = std::vector<char>().size(); or int n = std::difference(it1, it2);. The default list is empty, but one suggested list for a legacy codebase would be size_t;ptrdiff_t;size_type;differ- ence_type. PedanticMode When true, the check will warn on assigning a floating point constant to an integer value even if the floating point value is exactly representable in the destination type (e.g. int i = 1.0;). false by default. FAQ • What does "narrowing conversion from 'int' to 'float'" mean? An IEEE754 Floating Point number can represent all integer values in the range [-2^PrecisionBits, 2^PrecisionBits] where PrecisionBits is the number of bits in the mantissa. For float this would be [-2^23, 2^23], where int can represent values in the range [-2^31, 2^31-1]. • What does "implementation-defined" mean? You may have encountered messages like "narrowing conversion from 'un- signed int' to signed type 'int' is implementation-defined". The C/C++ standard does not mandate two's complement for signed integers, and so the compiler is free to define what the semantics are for converting an unsigned integer to signed integer. Clang's implementation uses the two's complement format. cppcoreguidelines-no-malloc This check handles C-Style memory management using malloc(), realloc(), calloc() and free(). It warns about its use and tries to suggest the use of an appropriate RAII object. Furthermore, it can be configured to check against a user-specified list of functions that are used for memory management (e.g. posix_memalign()). This check implements R.10 from the C++ Core Guidelines. There is no attempt made to provide fix-it hints, since manual resource management isn't easily transformed automatically into RAII. // Warns each of the following lines. // Containers like std::vector or std::string should be used. char* some_string = (char*) malloc(sizeof(char) * 20); char* some_string = (char*) realloc(sizeof(char) * 30); free(some_string); int* int_array = (int*) calloc(30, sizeof(int)); // Rather use a smartpointer or stack variable. struct some_struct* s = (struct some_struct*) malloc(sizeof(struct some_struct)); Options Allocations Semicolon-separated list of fully qualified names of memory al- location functions. Defaults to ::malloc;::calloc. Deallocations Semicolon-separated list of fully qualified names of memory al- location functions. Defaults to ::free. Reallocations Semicolon-separated list of fully qualified names of memory al- location functions. Defaults to ::realloc. cppcoreguidelines-no-suspend-with-lock Flags coroutines that suspend while a lock guard is in scope at the suspension point. When a coroutine suspends, any mutexes held by the coroutine will re- main locked until the coroutine resumes and eventually destructs the lock guard. This can lead to long periods with a mutex held and runs the risk of deadlock. Instead, locks should be released before suspending a coroutine. This check only checks suspending coroutines while a lock_guard is in scope; it does not consider manual locking or unlocking of mutexes, e.g., through calls to std::mutex::lock(). Examples: future bad_coro() { std::lock_guard lock{mtx}; ++some_counter; co_await something(); // Suspending while holding a mutex } future good_coro() { { std::lock_guard lock{mtx}; ++some_counter; } // Destroy the lock_guard to release the mutex before suspending the coroutine co_await something(); // Suspending while holding a mutex } This check implements CP.52 from the C++ Core Guidelines. cppcoreguidelines-noexcept-destructor This check implements C.37 from the C++ Core Guidelines. The cppcoreguidelines-noexcept-destructor check is an alias, please see performance-noexcept-destructor for more information. cppcoreguidelines-noexcept-move-operations This check implements C.66 from the C++ Core Guidelines. The cppcoreguidelines-noexcept-move-operations check is an alias, please see performance-noexcept-move-constructor for more information. cppcoreguidelines-noexcept-swap This check implements C.83 , C.84 and C.85 from the C++ Core Guide- lines. The cppcoreguidelines-noexcept-swap check is an alias, please see performance-noexcept-swap for more information. cppcoreguidelines-non-private-member-variables-in-classes The cppcoreguidelines-non-private-member-variables-in-classes check is an alias, please see misc-non-private-member-variables-in-classes for more information. cppcoreguidelines-owning-memory This check implements the type-based semantics of gsl::owner<T*>, which allows static analysis on code, that uses raw pointers to handle re- sources like dynamic memory, but won't introduce RAII concepts. This check implements I.11, C.33, R.3 and GSL.Views from the C++ Core Guidelines. The definition of a gsl::owner<T*> is straight forward namespace gsl { template <typename T> owner = T; } It is therefore simple to introduce the owner even without using an im- plementation of the Guideline Support Library. All checks are purely type based and not (yet) flow sensitive. The following examples will demonstrate the correct and incorrect ini- tializations of owners, assignment is handled the same way. Note that both new and malloc()-like resource functions are considered to produce resources. // Creating an owner with factory functions is checked. gsl::owner<int*> function_that_returns_owner() { return gsl::owner<int*>(new int(42)); } // Dynamic memory must be assigned to an owner int* Something = new int(42); // BAD, will be caught gsl::owner<int*> Owner = new int(42); // Good gsl::owner<int*> Owner = new int[42]; // Good as well // Returned owner must be assigned to an owner int* Something = function_that_returns_owner(); // Bad, factory function gsl::owner<int*> Owner = function_that_returns_owner(); // Good, result lands in owner // Something not a resource or owner should not be assigned to owners int Stack = 42; gsl::owner<int*> Owned = &Stack; // Bad, not a resource assigned In the case of dynamic memory as resource, only gsl::owner<T*> vari- ables are allowed to be deleted. // Example Bad, non-owner as resource handle, will be caught. int* NonOwner = new int(42); // First warning here, since new must land in an owner delete NonOwner; // Second warning here, since only owners are allowed to be deleted // Example Good, Ownership correctly stated gsl::owner<int*> Owner = new int(42); // Good delete Owner; // Good as well, statically enforced, that only owners get deleted The check will furthermore ensure, that functions, that expect a gsl::owner<T*> as argument get called with either a gsl::owner<T*> or a newly created resource. void expects_owner(gsl::owner<int*> o) { delete o; } // Bad Code int NonOwner = 42; expects_owner(&NonOwner); // Bad, will get caught // Good Code gsl::owner<int*> Owner = new int(42); expects_owner(Owner); // Good expects_owner(new int(42)); // Good as well, recognized created resource // Port legacy code for better resource-safety gsl::owner<FILE*> File = fopen("my_file.txt", "rw+"); FILE* BadFile = fopen("another_file.txt", "w"); // Bad, warned // ... use the file fclose(File); // Ok, File is annotated as 'owner<>' fclose(BadFile); // BadFile is not an 'owner<>', will be warned Options LegacyResourceProducers Semicolon-separated list of fully qualified names of legacy functions that create resources but cannot introduce gsl::owner<>. Defaults to ::malloc;::aligned_alloc;::real- loc;::calloc;::fopen;::freopen;::tmpfile. LegacyResourceConsumers Semicolon-separated list of fully qualified names of legacy functions expecting resource owners as pointer arguments but cannot introduce gsl::owner<>. Defaults to ::free;::real- loc;::freopen;::fclose. Limitations Using gsl::owner<T*> in a typedef or alias is not handled correctly. using heap_int = gsl::owner<int*>; heap_int allocated = new int(42); // False positive! The gsl::owner<T*> is declared as a templated type alias. In template functions and classes, like in the example below, the information of the type aliases gets lost. Therefore using gsl::owner<T*> in a heavy templated code base might lead to false positives. Known code constructs that do not get diagnosed correctly are: • std::exchange • std::vector<gsl::owner<T*>> // This template function works as expected. Type information doesn't get lost. template <typename T> void delete_owner(gsl::owner<T*> owned_object) { delete owned_object; // Everything alright } gsl::owner<int*> function_that_returns_owner() { return gsl::owner<int*>(new int(42)); } // Type deduction does not work for auto variables. // This is caught by the check and will be noted accordingly. auto OwnedObject = function_that_returns_owner(); // Type of OwnedObject will be int* // Problematic function template that looses the typeinformation on owner template <typename T> void bad_template_function(T some_object) { // This line will trigger the warning, that a non-owner is assigned to an owner gsl::owner<T*> new_owner = some_object; } // Calling the function with an owner still yields a false positive. bad_template_function(gsl::owner<int*>(new int(42))); // The same issue occurs with templated classes like the following. template <typename T> class OwnedValue { public: const T getValue() const { return _val; } private: T _val; }; // Code, that yields a false positive. OwnedValue<gsl::owner<int*>> Owner(new int(42)); // Type deduction yield T -> int * // False positive, getValue returns int* and not gsl::owner<int*> gsl::owner<int*> OwnedInt = Owner.getValue(); Another limitation of the current implementation is only the type based checking. Suppose you have code like the following: // Two owners with assigned resources gsl::owner<int*> Owner1 = new int(42); gsl::owner<int*> Owner2 = new int(42); Owner2 = Owner1; // Conceptual Leak of initial resource of Owner2! Owner1 = nullptr; The semantic of a gsl::owner<T*> is mostly like a std::unique_ptr<T>, therefore assignment of two gsl::owner<T*> is considered a move, which requires that the resource Owner2 must have been released before the assignment. This kind of condition could be caught in later improve- ments of this check with flowsensitive analysis. Currently, the Clang Static Analyzer catches this bug for dynamic memory, but not for gen- eral types of resources. cppcoreguidelines-prefer-member-initializer Finds member initializations in the constructor body which can be con- verted into member initializers of the constructor instead. This not only improves the readability of the code but also positively affects its performance. Class-member assignments inside a control statement or following the first control statement are ignored. This check implements C.49 from the C++ Core Guidelines. If the language version is C++ 11 or above, the constructor is the de- fault constructor of the class, the field is not a bitfield (only in case of earlier language version than C++ 20), furthermore the assigned value is a literal, negated literal or enum constant then the preferred place of the initialization is at the class member declaration. This latter rule is C.48 from the C++ Core Guidelines. Please note, that this check does not enforce this latter rule for ini- tializations already implemented as member initializers. For that pur- pose see check modernize-use-default-member-init. NOTE: Enforcement of rule C.48 in this check is deprecated, to be removed in clang-tidy version 19 (only C.49 will be enforced by this check then). Please use cppcoreguidelines-use-default-member-init to en- force rule C.48. Example 1 class C { int n; int m; public: C() { n = 1; // Literal in default constructor if (dice()) return; m = 1; } }; Here n can be initialized using a default member initializer, unlike m, as m's initialization follows a control statement (if): class C { int n{1}; int m; public: C() { if (dice()) return; m = 1; } }; Example 2 class C { int n; int m; public: C(int nn, int mm) { n = nn; // Neither default constructor nor literal if (dice()) return; m = mm; } }; Here n can be initialized in the constructor initialization list, un- like m, as m's initialization follows a control statement (if): C(int nn, int mm) : n(nn) { if (dice()) return; m = mm; } UseAssignment Note: this option is deprecated, to be removed in clang-tidy version 19. Please use the UseAssignment option from cppcoreguidelines-use-default-member-init instead. If this option is set to true (by default UseAssignment from modernize-use-default-member-init will be used), the check will initialize members with an assignment. In this case the fix of the first example looks like this: class C { int n = 1; int m; public: C() { if (dice()) return; m = 1; } }; cppcoreguidelines-pro-bounds-array-to-pointer-decay This check flags all array to pointer decays. Pointers should not be used as arrays. span<T> is a bounds-checked, safe alternative to using pointers to access arrays. This rule is part of the Bounds safety (Bounds 3) profile from the C++ Core Guidelines. cppcoreguidelines-pro-bounds-constant-array-index This check flags all array subscript expressions on static arrays and std::arrays that either do not have a constant integer expression index or are out of bounds (for std::array). For out-of-bounds checking of static arrays, see the -Warray-bounds Clang diagnostic. This rule is part of the Bounds safety (Bounds 2) profile from the C++ Core Guidelines. Optionally, this check can generate fixes using gsl::at for indexing. Options GslHeader The check can generate fixes after this option has been set to the name of the include file that contains gsl::at(), e.g. "gsl/gsl.h". IncludeStyle A string specifying which include-style is used, llvm or google. Default is llvm. cppcoreguidelines-pro-bounds-pointer-arithmetic This check flags all usage of pointer arithmetic, because it could lead to an invalid pointer. Subtraction of two pointers is not flagged by this check. Pointers should only refer to single objects, and pointer arithmetic is fragile and easy to get wrong. span<T> is a bounds-checked, safe type for accessing arrays of data. This rule is part of the Bounds safety (Bounds 1) profile from the C++ Core Guidelines. cppcoreguidelines-pro-type-const-cast Imposes limitations on the use of const_cast within C++ code. It de- pends on the StrictMode option setting to determine whether it should flag all instances of const_cast or only those that remove either const or volatile qualifier. Modifying a variable that has been declared as const in C++ is gener- ally considered undefined behavior, and this remains true even when us- ing const_cast. In C++, the const qualifier indicates that a variable is intended to be read-only, and the compiler enforces this by disal- lowing any attempts to change the value of that variable. Removing the volatile qualifier in C++ can have serious consequences. This qualifier indicates that a variable's value can change unpre- dictably, and removing it may lead to undefined behavior, optimization problems, and debugging challenges. It's essential to retain the volatile qualifier in situations where the variable's volatility is a crucial aspect of program correctness and reliability. This rule is part of the Type safety (Type 3) profile and ES.50: Dont cast away const rule from the C++ Core Guidelines. Options StrictMode When this setting is set to true, it means that any usage of const_cast is not allowed. On the other hand, when it's set to false, it permits casting to const or volatile types. Default value is false. cppcoreguidelines-pro-type-cstyle-cast This check flags all use of C-style casts that perform a static_cast downcast, const_cast, or reinterpret_cast. Use of these casts can violate type safety and cause the program to ac- cess a variable that is actually of type X to be accessed as if it were of an unrelated type Z. Note that a C-style (T)expression cast means to perform the first of the following that is possible: a const_cast, a static_cast, a static_cast followed by a const_cast, a reinter- pret_cast, or a reinterpret_cast followed by a const_cast. This rule bans (T)expression only when used to perform an unsafe cast. This rule is part of the Type safety (Type.4) profile from the C++ Core Guidelines. cppcoreguidelines-pro-type-member-init The check flags user-defined constructor definitions that do not ini- tialize all fields that would be left in an undefined state by default construction, e.g. builtins, pointers and record types without user-provided default constructors containing at least one such type. If these fields aren't initialized, the constructor will leave some of the memory in an undefined state. For C++11 it suggests fixes to add in-class field initializers. For older versions it inserts the field initializers into the constructor initializer list. It will also initialize any direct base classes that need to be zeroed in the constructor initializer list. The check takes assignment of fields in the constructor body into ac- count but generates false positives for fields initialized in methods invoked in the constructor body. The check also flags variables with automatic storage duration that have record types without a user-provided constructor and are not ini- tialized. The suggested fix is to zero initialize the variable via {} for C++11 and beyond or = {} for older language versions. Options IgnoreArrays If set to true, the check will not warn about array members that are not zero-initialized during construction. For performance critical code, it may be important to not initialize fixed-size array members. Default is false. UseAssignment If set to true, the check will provide fix-its with literal ini- tializers ( int i = 0; ) instead of curly braces ( int i{}; ). This rule is part of the Type safety (Type.6) profile from the C++ Core Guidelines. cppcoreguidelines-pro-type-reinterpret-cast This check flags all uses of reinterpret_cast in C++ code. Use of these casts can violate type safety and cause the program to ac- cess a variable that is actually of type X to be accessed as if it were of an unrelated type Z. This rule is part of the Type safety (Type.1.1) profile from the C++ Core Guidelines. cppcoreguidelines-pro-type-static-cast-downcast This check flags all usages of static_cast, where a base class is casted to a derived class. In those cases, a fix-it is provided to con- vert the cast to a dynamic_cast. Use of these casts can violate type safety and cause the program to ac- cess a variable that is actually of type X to be accessed as if it were of an unrelated type Z. This rule is part of the Type safety (Type.2) profile from the C++ Core Guidelines. Options StrictMode When set to false, no warnings are emitted for casts on non-polymorphic types. Default is true. cppcoreguidelines-pro-type-union-access This check flags all access to members of unions. Passing unions as a whole is not flagged. Reading from a union member assumes that member was the last one writ- ten, and writing to a union member assumes another member with a non- trivial destructor had its destructor called. This is fragile because it cannot generally be enforced to be safe in the language and so re- lies on programmer discipline to get it right. This rule is part of the Type safety (Type.7) profile from the C++ Core Guidelines. cppcoreguidelines-pro-type-vararg This check flags all calls to c-style vararg functions and all use of va_arg. To allow for SFINAE use of vararg functions, a call is not flagged if a literal 0 is passed as the only vararg argument or function is used in unevaluated context. Passing to varargs assumes the correct type will be read. This is frag- ile because it cannot generally be enforced to be safe in the language and so relies on programmer discipline to get it right. This rule is part of the Type safety (Type.8) profile from the C++ Core Guidelines. cppcoreguidelines-rvalue-reference-param-not-moved Warns when an rvalue reference function parameter is never moved within the function body. Rvalue reference parameters indicate a parameter that should be moved with std::move from within the function body. Any such parameter that is never moved is confusing and potentially indicative of a buggy pro- gram. Example: void logic(std::string&& Input) { std::string Copy(Input); // Oops - forgot to std::move } Note that parameters that are unused and marked as such will not be di- agnosed. Example: void conditional_use([[maybe_unused]] std::string&& Input) { // No diagnostic here since Input is unused and marked as such } Options AllowPartialMove If set to true, the check accepts std::move calls containing any subexpression containing the parameter. CppCoreGuideline F.18 officially mandates that the parameter itself must be moved. Default is false. // 'p' is flagged by this check if and only if AllowPartialMove is false void move_members_of(pair<Obj, Obj>&& p) { pair<Obj, Obj> other; other.first = std::move(p.first); other.second = std::move(p.second); } // 'p' is never flagged by this check void move_whole_pair(pair<Obj, Obj>&& p) { pair<Obj, Obj> other = std::move(p); } IgnoreUnnamedParams If set to true, the check ignores unnamed rvalue reference para- meters. Default is false. IgnoreNonDeducedTemplateTypes If set to true, the check ignores non-deduced template type rvalue reference parameters. Default is false. template <class T> struct SomeClass { // Below, 'T' is not deduced and 'T&&' is an rvalue reference type. // This will be flagged if and only if IgnoreNonDeducedTemplateTypes is // false. One suggested fix would be to specialize the class for 'T' and // 'T&' separately (e.g., see std::future), or allow only one of 'T' or // 'T&' instantiations of SomeClass (e.g., see std::optional). SomeClass(T&& t) { } }; // Never flagged, since 'T' is a forwarding reference in a deduced context template <class T> void forwarding_ref(T&& t) { T other = std::forward<T>(t); } This check implements F.18 from the C++ Core Guidelines. cppcoreguidelines-slicing Flags slicing of member variables or vtable. Slicing happens when copy- ing a derived object into a base object: the members of the derived ob- ject (both member variables and virtual member functions) will be dis- carded. This can be misleading especially for member function slicing, for example: struct B { int a; virtual int f(); }; struct D : B { int b; int f() override; }; void use(B b) { // Missing reference, intended? b.f(); // Calls B::f. } D d; use(d); // Slice. This check implements ES.63 and C.145 from the C++ Core Guidelines. cppcoreguidelines-special-member-functions The check finds classes where some but not all of the special member functions are defined. By default the compiler defines a copy constructor, copy assignment op- erator, move constructor, move assignment operator and destructor. The default can be suppressed by explicit user-definitions. The relation- ship between which functions will be suppressed by definitions of other functions is complicated and it is advised that all five are defaulted or explicitly defined. Note that defining a function with = delete is considered to be a defi- nition. This check implements C.21 from the C++ Core Guidelines. Options AllowSoleDefaultDtor When set to true (default is false), this check will only trig- ger on destructors if they are defined and not defaulted. struct A { // This is fine. virtual ~A() = default; }; struct B { // This is not fine. ~B() {} }; struct C { // This is not checked, because the destructor might be defaulted in // another translation unit. ~C(); }; AllowMissingMoveFunctions When set to true (default is false), this check doesn't flag classes which define no move operations at all. It still flags classes which define only one of either move constructor or move assignment operator. With this option enabled, the following class won't be flagged: struct A { A(const A&); A& operator=(const A&); ~A(); }; AllowMissingMoveFunctionsWhenCopyIsDeleted When set to true (default is false), this check doesn't flag classes which define deleted copy operations but don't define move operations. This flag is related to Google C++ Style Guide https://google.github.io/styleguide/cppguide.html#Copyable_Movable_Types. With this option enabled, the following class won't be flagged: struct A { A(const A&) = delete; A& operator=(const A&) = delete; ~A(); }; cppcoreguidelines-use-default-member-init This check implements C.48 from the C++ Core Guidelines. The cppcoreguidelines-use-default-member-init check is an alias, please see modernize-use-default-member-init for more information. cppcoreguidelines-virtual-class-destructor Finds virtual classes whose destructor is neither public and virtual nor protected and non-virtual. A virtual class's destructor should be specified in one of these ways to prevent undefined behavior. This check implements C.35 from the C++ Core Guidelines. Note that this check will diagnose a class with a virtual method re- gardless of whether the class is used as a base class or not. Fixes are available for user-declared and implicit destructors that are either public and non-virtual or protected and virtual. No fixes are offered for private destructors. There, the decision whether to make them private and virtual or protected and non-virtual depends on the use case and is thus left to the user. Example For example, the following classes/structs get flagged by the check since they violate guideline C.35: struct Foo { // NOK, protected destructor should not be virtual virtual void f(); protected: virtual ~Foo(){} }; class Bar { // NOK, public destructor should be virtual virtual void f(); public: ~Bar(){} }; This would be rewritten to look like this: struct Foo { // OK, destructor is not virtual anymore virtual void f(); protected: ~Foo(){} }; class Bar { // OK, destructor is now virtual virtual void f(); public: virtual ~Bar(){} }; darwin-avoid-spinlock Finds usages of OSSpinlock, which is deprecated due to potential live- lock problems. This check will detect following function invocations: • OSSpinlockLock • OSSpinlockTry • OSSpinlockUnlock The corresponding information about the problem of OSSpinlock: https://blog.postmates.com/why-spinlocks-are-bad-on-ios-b69fc5221058 darwin-dispatch-once-nonstatic Finds declarations of dispatch_once_t variables without static or global storage. The behavior of using dispatch_once_t predicates with automatic or dynamic storage is undefined by libdispatch, and should be avoided. It is a common pattern to have functions initialize internal static or global data once when the function runs, but programmers have been known to miss the static on the dispatch_once_t predicate, leading to an uninitialized flag value at the mercy of the stack. Programmers have also been known to make dispatch_once_t variables be members of structs or classes, with the intent to lazily perform some expensive struct or class member initialization only once; however, this violates the libdispatch requirements. See the discussion section of Apple's dispatch_once documentation for more information. fuchsia-default-arguments-calls Warns if a function or method is called with default arguments. For example, given the declaration: int foo(int value = 5) { return value; } A function call expression that uses a default argument will be diag- nosed. Calling it without defaults will not cause a warning: foo(); // warning foo(0); // no warning See the features disallowed in Fuchsia at https://fuchsia.dev/fuchsia-src/development/languages/c-cpp/cxx?hl=en fuchsia-default-arguments-declarations Warns if a function or method is declared with default parameters. For example, the declaration: int foo(int value = 5) { return value; } will cause a warning. See the features disallowed in Fuchsia at https://fuchsia.dev/fuchsia-src/development/languages/c-cpp/cxx?hl=en fuchsia-header-anon-namespaces The fuchsia-header-anon-namespaces check is an alias, please see google-build-namespace for more information. fuchsia-multiple-inheritance Warns if a class inherits from multiple classes that are not pure vir- tual. For example, declaring a class that inherits from multiple concrete classes is disallowed: class Base_A { public: virtual int foo() { return 0; } }; class Base_B { public: virtual int bar() { return 0; } }; // Warning class Bad_Child1 : public Base_A, Base_B {}; A class that inherits from a pure virtual is allowed: class Interface_A { public: virtual int foo() = 0; }; class Interface_B { public: virtual int bar() = 0; }; // No warning class Good_Child1 : public Interface_A, Interface_B { virtual int foo() override { return 0; } virtual int bar() override { return 0; } }; See the features disallowed in Fuchsia at https://fuchsia.dev/fuchsia-src/development/languages/c-cpp/cxx?hl=en fuchsia-overloaded-operator Warns if an operator is overloaded, except for the assignment (copy and move) operators. For example: int operator+(int); // Warning B &operator=(const B &Other); // No warning B &operator=(B &&Other) // No warning See the features disallowed in Fuchsia at https://fuchsia.dev/fuchsia-src/development/languages/c-cpp/cxx?hl=en fuchsia-statically-constructed-objects Warns if global, non-trivial objects with static storage are con- structed, unless the object is statically initialized with a constexpr constructor or has no explicit constructor. For example: class A {}; class B { public: B(int Val) : Val(Val) {} private: int Val; }; class C { public: constexpr C(int Val) : Val(Val) {} C(int Val1, int Val2) : Val(Val1+Val2) {} private: int Val; }; static A a; // No warning, as there is no explicit constructor static C c(0); // No warning, as constructor is constexpr static B b(0); // Warning, as constructor is not constexpr static C c2(0, 1); // Warning, as constructor is not constexpr static int i; // No warning, as it is trivial extern int get_i(); static C c3(get_i());// Warning, as the constructor is dynamically initialized See the features disallowed in Fuchsia at https://fuchsia.dev/fuchsia-src/development/languages/c-cpp/cxx?hl=en fuchsia-trailing-return Functions that have trailing returns are disallowed, except for those using decltype specifiers and lambda with otherwise unutterable return types. For example: // No warning int add_one(const int arg) { return arg; } // Warning auto get_add_one() -> int (*)(const int) { return add_one; } Exceptions are made for lambdas and decltype specifiers: // No warning auto lambda = [](double x, double y) -> double {return x + y;}; // No warning template <typename T1, typename T2> auto fn(const T1 &lhs, const T2 &rhs) -> decltype(lhs + rhs) { return lhs + rhs; } See the features disallowed in Fuchsia at https://fuchsia.dev/fuchsia-src/development/languages/c-cpp/cxx?hl=en fuchsia-virtual-inheritance Warns if classes are defined with virtual inheritance. For example, classes should not be defined with virtual inheritance: class B : public virtual A {}; // warning See the features disallowed in Fuchsia at https://fuchsia.dev/fuchsia-src/development/languages/c-cpp/cxx?hl=en google-build-explicit-make-pair Check that make_pair's template arguments are deduced. G++ 4.6 in C++11 mode fails badly if make_pair's template arguments are specified explicitly, and such use isn't intended in any case. Corresponding cpplint.py check name: build/explicit_make_pair. google-build-namespaces cert-dcl59-cpp redirects here as an alias for this check. fuch- sia-header-anon-namespaces redirects here as an alias for this check. Finds anonymous namespaces in headers. https://google.github.io/styleguide/cppguide.html#Namespaces Corresponding cpplint.py check name: build/namespaces. Options HeaderFileExtensions Note: this option is deprecated, it will be removed in clang-tidy version 19. Please use the global configuration op- tion HeaderFileExtensions. A comma-separated list of filename extensions of header files (the filename extensions should not include "." prefix). Default is "h,hh,hpp,hxx". For header files without an extension, use an empty string (if there are no other desired extensions) or leave an empty element in the list. E.g., "h,hh,hpp,hxx," (note the trailing comma). google-build-using-namespace Finds using namespace directives. The check implements the following rule of the Google C++ Style Guide: You may not use a using-directive to make all names from a namespace available. // Forbidden -- This pollutes the namespace. using namespace foo; Corresponding cpplint.py check name: build/namespaces. google-default-arguments Checks that default arguments are not given for virtual methods. See https://google.github.io/styleguide/cppguide.html#Default_Arguments google-explicit-constructor Checks that constructors callable with a single argument and conversion operators are marked explicit to avoid the risk of unintentional im- plicit conversions. Consider this example: struct S { int x; operator bool() const { return true; } }; bool f() { S a{1}; S b{2}; return a == b; } The function will return true, since the objects are implicitly con- verted to bool before comparison, which is unlikely to be the intent. The check will suggest inserting explicit before the constructor or conversion operator declaration. However, copy and move constructors should not be explicit, as well as constructors taking a single ini- tializer_list argument. This code: struct S { S(int a); explicit S(const S&); operator bool() const; ... will become struct S { explicit S(int a); S(const S&); explicit operator bool() const; ... See https://google.github.io/styleguide/cppguide.html#Explicit_Constructors google-global-names-in-headers Flag global namespace pollution in header files. Right now it only triggers on using declarations and directives. The relevant style guide section is https://google.github.io/styleguide/cppguide.html#Namespaces. Options HeaderFileExtensions Note: this option is deprecated, it will be removed in clang-tidy version 19. Please use the global configuration op- tion HeaderFileExtensions. A comma-separated list of filename extensions of header files (the filename extensions should not contain "." prefix). Default is "h". For header files without an extension, use an empty string (if there are no other desired extensions) or leave an empty element in the list. E.g., "h,hh,hpp,hxx," (note the trailing comma). google-objc-avoid-nsobject-new Finds calls to +new or overrides of it, which are prohibited by the Google Objective-C style guide. The Google Objective-C style guide forbids calling +new or overriding it in class implementations, preferring +alloc and -init methods to in- stantiate objects. An example: NSDate *now = [NSDate new]; Foo *bar = [Foo new]; Instead, code should use +alloc/-init or class factory methods. NSDate *now = [NSDate date]; Foo *bar = [[Foo alloc] init]; This check corresponds to the Google Objective-C Style Guide rule Do Not Use +new. google-objc-avoid-throwing-exception Finds uses of throwing exceptions usages in Objective-C files. For the same reason as the Google C++ style guide, we prefer not throw- ing exceptions from Objective-C code. The corresponding C++ style guide rule: https://google.github.io/styleguide/cppguide.html#Exceptions Instead, prefer passing in NSError ** and return BOOL to indicate suc- cess or failure. A counterexample: - (void)readFile { if ([self isError]) { @throw [NSException exceptionWithName:...]; } } Instead, returning an error via NSError ** is preferred: - (BOOL)readFileWithError:(NSError **)error { if ([self isError]) { *error = [NSError errorWithDomain:...]; return NO; } return YES; } The corresponding style guide rule: https://google.github.io/styleguide/objcguide.html#avoid-throwing-exceptions google-objc-function-naming Finds function declarations in Objective-C files that do not follow the pattern described in the Google Objective-C Style Guide. The corresponding style guide rule can be found here: https://google.github.io/styleguide/objcguide.html#function-names All function names should be in Pascal case. Functions whose storage class is not static should have an appropriate prefix. The following code sample does not follow this pattern: static bool is_positive(int i) { return i > 0; } bool IsNegative(int i) { return i < 0; } The sample above might be corrected to the following code: static bool IsPositive(int i) { return i > 0; } bool *ABCIsNegative(int i) { return i < 0; } google-objc-global-variable-declaration Finds global variable declarations in Objective-C files that do not follow the pattern of variable names in Google's Objective-C Style Guide. The corresponding style guide rule: https://google.github.io/styleguide/objcguide.html#variable-names All the global variables should follow the pattern of g[A-Z].* (vari- ables) or k[A-Z].* (constants). The check will suggest a variable name that follows the pattern if it can be inferred from the original name. For code: static NSString* myString = @"hello"; The fix will be: static NSString* gMyString = @"hello"; Another example of constant: static NSString* const myConstString = @"hello"; The fix will be: static NSString* const kMyConstString = @"hello"; However for code that prefixed with non-alphabetical characters like: static NSString* __anotherString = @"world"; The check will give a warning message but will not be able to suggest a fix. The user needs to fix it on their own. google-readability-avoid-underscore-in-googletest-name Checks whether there are underscores in googletest test suite names and test names in test macros: • TEST • TEST_F • TEST_P • TYPED_TEST • TYPED_TEST_P The FRIEND_TEST macro is not included. For example: TEST(TestSuiteName, Illegal_TestName) {} TEST(Illegal_TestSuiteName, TestName) {} would trigger the check. Underscores are not allowed in test suite name nor test names. The DISABLED_ prefix, which may be used to disable test suites and in- dividual tests, is removed from the test suite name and test name be- fore checking for underscores. This check does not propose any fixes. google-readability-braces-around-statements The google-readability-braces-around-statements check is an alias, please see readability-braces-around-statements for more information. google-readability-casting Finds usages of C-style casts. https://google.github.io/styleguide/cppguide.html#Casting Corresponding cpplint.py check name: readability/casting. This check is similar to -Wold-style-cast, but it suggests automated fixes in some cases. The reported locations should not be different from the ones generated by -Wold-style-cast. google-readability-function-size The google-readability-function-size check is an alias, please see readability-function-size for more information. google-readability-namespace-comments The google-readability-namespace-comments check is an alias, please see llvm-namespace-comment for more information. google-readability-todo Finds TODO comments without a username or bug number. The relevant style guide section is https://google.github.io/styleguide/cppguide.html#TODO_Comments. Corresponding cpplint.py check: readability/todo google-runtime-int Finds uses of short, long and long long and suggest replacing them with u?intXX(_t)?. The corresponding style guide rule: https://google.github.io/styleguide/cppguide.html#Integer_Types. Corresponding cpplint.py check: runtime/int. Options UnsignedTypePrefix A string specifying the unsigned type prefix. Default is uint. SignedTypePrefix A string specifying the signed type prefix. Default is int. TypeSuffix A string specifying the type suffix. Default is an empty string. google-runtime-operator Finds overloads of unary operator &. https://google.github.io/styleguide/cppguide.html#Operator_Overloading Corresponding cpplint.py check name: runtime/operator. google-upgrade-googletest-case Finds uses of deprecated Google Test version 1.9 APIs with names con- taining case and replaces them with equivalent APIs with suite. All names containing case are being replaced to be consistent with the meanings of "test case" and "test suite" as used by the International Software Testing Qualifications Board and ISO 29119. The new names are a part of Google Test version 1.9 (release pending). It is recommended that users update their dependency to version 1.9 and then use this check to remove deprecated names. The affected APIs are: • Member functions of testing::Test, testing::TestInfo, test- ing::TestEventListener, testing::UnitTest, and any type inheriting from these types • The macros TYPED_TEST_CASE, TYPED_TEST_CASE_P, REGIS- TER_TYPED_TEST_CASE_P, and INSTANTIATE_TYPED_TEST_CASE_P • The type alias testing::TestCase Examples of fixes created by this check: class FooTest : public testing::Test { public: static void SetUpTestCase(); static void TearDownTestCase(); }; TYPED_TEST_CASE(BarTest, BarTypes); becomes class FooTest : public testing::Test { public: static void SetUpTestSuite(); static void TearDownTestSuite(); }; TYPED_TEST_SUITE(BarTest, BarTypes); For better consistency of user code, the check renames both virtual and non-virtual member functions with matching names in derived types. The check tries to provide only a warning when a fix cannot be made safely, as is the case with some template and macro uses. hicpp-avoid-c-arrays The hicpp-avoid-c-arrays check is an alias, please see modernize-avoid-c-arrays for more information. It partly enforces the rule 4.1.1. hicpp-avoid-goto The hicpp-avoid-goto check is an alias, please see cppcoreguidelines-avoid-goto for more information. It enforces the rule 6.3.1. hicpp-braces-around-statements The hicpp-braces-around-statements check is an alias, please see readability-braces-around-statements for more information. It enforces the rule 6.1.1. hicpp-deprecated-headers The hicpp-deprecated-headers check is an alias, please see modernize-deprecated-headers for more information. It enforces the rule 1.3.3. hicpp-exception-baseclass Ensure that every value that in a throw expression is an instance of std::exception. This enforces rule 15.1 of the High Integrity C++ Coding Standard. class custom_exception {}; void throwing() noexcept(false) { // Problematic throw expressions. throw int(42); throw custom_exception(); } class mathematical_error : public std::exception {}; void throwing2() noexcept(false) { // These kind of throws are ok. throw mathematical_error(); throw std::runtime_error(); throw std::exception(); } hicpp-explicit-conversions This check is an alias for google-explicit-constructor. Used to en- force parts of rule 5.4.1. This check will enforce that constructors and conversion operators are marked explicit. Other forms of casting checks are implemented in other places. The following checks can be used to check for more forms of casting: • cppcoreguidelines-pro-type-static-cast-downcast • cppcoreguidelines-pro-type-reinterpret-cast • cppcoreguidelines-pro-type-const-cast • cppcoreguidelines-pro-type-cstyle-cast hicpp-function-size This check is an alias for readability-function-size. Useful to en- force multiple sections on function complexity. • rule 8.2.2 • rule 8.3.1 • rule 8.3.2 hicpp-ignored-remove-result Ensure that the result of std::remove, std::remove_if and std::unique are not ignored according to rule 17.5.1. The mutating algorithms std::remove, std::remove_if and both overloads of std::unique operate by swapping or moving elements of the range they are operating over. On completion, they return an iterator to the last valid element. In the majority of cases the correct behavior is to use this result as the first operand in a call to std::erase. This check is a subset of bugprone-unused-return-value and depending on used options it can be superfluous to enable both checks. Options AllowCastToVoid Controls whether casting return values to void is permitted. De- fault: true. hicpp-invalid-access-moved This check is an alias for bugprone-use-after-move. Implements parts of the rule 8.4.1 to check if moved-from objects are accessed. hicpp-member-init This check is an alias for cppcoreguidelines-pro-type-member-init. Im- plements the check for rule 12.4.2 to initialize class members in the right order. hicpp-move-const-arg The hicpp-move-const-arg check is an alias, please see performance-move-const-arg for more information. It enforces the rule 17.3.1. hicpp-multiway-paths-covered This check discovers situations where code paths are not fully-covered. It furthermore suggests using if instead of switch if the code will be more clear. The rule 6.1.2 and rule 6.1.4 of the High Integrity C++ Coding Standard are enforced. if-else if chains that miss a final else branch might lead to unex- pected program execution and be the result of a logical error. If the missing else branch is intended you can leave it empty with a clarify- ing comment. This warning can be noisy on some code bases, so it is disabled by default. void f1() { int i = determineTheNumber(); if(i > 0) { // Some Calculation } else if (i < 0) { // Precondition violated or something else. } // ... } Similar arguments hold for switch statements which do not cover all possible code paths. // The missing default branch might be a logical error. It can be kept empty // if there is nothing to do, making it explicit. void f2(int i) { switch (i) { case 0: // something break; case 1: // something else break; } // All other numbers? } // Violates this rule as well, but already emits a compiler warning (-Wswitch). enum Color { Red, Green, Blue, Yellow }; void f3(enum Color c) { switch (c) { case Red: // We can't drive for now. break; case Green: // We are allowed to drive. break; } // Other cases missing } The rule 6.1.4 requires every switch statement to have at least two case labels other than a default label. Otherwise, the switch could be better expressed with an if statement. Degenerated switch statements without any labels are caught as well. // Degenerated switch that could be better written as `if` int i = 42; switch(i) { case 1: // do something here default: // do something else here } // Should rather be the following: if (i == 1) { // do something here } else { // do something here } // A completely degenerated switch will be diagnosed. int i = 42; switch(i) {} Options WarnOnMissingElse Boolean flag that activates a warning for missing else branches. Default is false. hicpp-named-parameter This check is an alias for readability-named-parameter. Implements rule 8.2.1. hicpp-new-delete-operators This check is an alias for misc-new-delete-overloads. Implements rule 12.3.1 to ensure the new and delete operators have the correct signa- ture. hicpp-no-array-decay The hicpp-no-array-decay check is an alias, please see cppcoreguidelines-pro-bounds-array-to-pointer-decay for more informa- tion. It enforces the rule 4.1.1. hicpp-no-assembler Checks for assembler statements. Use of inline assembly should be avoided since it restricts the portability of the code. This enforces rule 7.5.1 of the High Integrity C++ Coding Standard. hicpp-no-malloc The hicpp-no-malloc check is an alias, please see cppcoreguidelines-no-malloc for more information. It enforces the rule 5.3.2. hicpp-noexcept-move This check is an alias for performance-noexcept-move-constructor. Checks rule 12.5.4 to mark move assignment and move construction noex- cept. hicpp-signed-bitwise Finds uses of bitwise operations on signed integer types, which may lead to undefined or implementation defined behavior. The according rule is defined in the High Integrity C++ Standard, Sec- tion 5.6.1. Options IgnorePositiveIntegerLiterals If this option is set to true, the check will not warn on bit- wise operations with positive integer literals, e.g. ~0, 2 << 1, etc. Default value is false. hicpp-special-member-functions This check is an alias for cppcoreguidelines-special-member-functions. Checks that special member functions have the correct signature, ac- cording to rule 12.5.7. hicpp-static-assert The hicpp-static-assert check is an alias, please see misc-static-assert for more information. It enforces the rule 7.1.10. hicpp-undelegated-constructor This check is an alias for bugprone-undelegated-constructor. Partially implements rule 12.4.5 to find misplaced constructor calls inside a constructor. struct Ctor { Ctor(); Ctor(int); Ctor(int, int); Ctor(Ctor *i) { // All Ctor() calls result in a temporary object Ctor(); // did you intend to call a delegated constructor? Ctor(0); // did you intend to call a delegated constructor? Ctor(1, 2); // did you intend to call a delegated constructor? foo(); } }; hicpp-uppercase-literal-suffix The hicpp-uppercase-literal-suffix check is an alias, please see readability-uppercase-literal-suffix for more information. Partially implements rule 4.2.1 to ensure that the U suffix is writeln properly. hicpp-use-auto The hicpp-use-auto check is an alias, please see modernize-use-auto for more information. It enforces the rule 7.1.8. hicpp-use-emplace The hicpp-use-emplace check is an alias, please see modernize-use-emplace for more information. It enforces the rule 17.4.2. hicpp-use-equals-default This check is an alias for modernize-use-equals-default. Implements rule 12.5.1 to explicitly default special member functions. hicpp-use-equals-delete This check is an alias for modernize-use-equals-delete. Implements rule 12.5.1 to explicitly default or delete special member functions. hicpp-use-noexcept The hicpp-use-noexcept check is an alias, please see modernize-use-noexcept for more information. It enforces the rule 1.3.5. hicpp-use-nullptr The hicpp-use-nullptr check is an alias, please see modernize-use-nullptr for more information. It enforces the rule 2.5.3. hicpp-use-override This check is an alias for modernize-use-override. Implements rule 10.2.1 to declare a virtual function override when overriding. hicpp-vararg The hicpp-vararg check is an alias, please see cppcoreguidelines-pro-type-vararg for more information. It enforces the rule 14.1.1. linuxkernel-must-use-errs Checks Linux kernel code to see if it uses the results from the func- tions in linux/err.h. Also checks to see if code uses the results from functions that directly return a value from one of these error func- tions. This is important in the Linux kernel because ERR_PTR, PTR_ERR, IS_ERR, IS_ERR_OR_NULL, ERR_CAST, and PTR_ERR_OR_ZERO return values must be checked, since positive pointers and negative error codes are being used in the same context. These functions are marked with __at- tribute__((warn_unused_result)), but some kernel versions do not have this warning enabled for clang. Examples: /* Trivial unused call to an ERR function */ PTR_ERR_OR_ZERO(some_function_call()); /* A function that returns ERR_PTR. */ void *fn() { ERR_PTR(-EINVAL); } /* An invalid use of fn. */ fn(); llvm-else-after-return The llvm-else-after-return check is an alias, please see readability-else-after-return for more information. llvm-header-guard Finds and fixes header guards that do not adhere to LLVM style. Options HeaderFileExtensions Note: this option is deprecated, it will be removed in clang-tidy version 19. Please use the global configuration op- tion HeaderFileExtensions. A comma-separated list of filename extensions of header files (the filename extensions should not include "." prefix). Default is "h,hh,hpp,hxx". For header files without an extension, use an empty string (if there are no other desired extensions) or leave an empty element in the list. E.g., "h,hh,hpp,hxx," (note the trailing comma). llvm-include-order Checks the correct order of #includes. See https://llvm.org/docs/CodingStandards.html#include-style llvm-namespace-comment google-readability-namespace-comments redirects here as an alias for this check. Checks that long namespaces have a closing comment. https://llvm.org/docs/CodingStandards.html#namespace-indentation https://google.github.io/styleguide/cppguide.html#Namespaces namespace n1 { void f(); } // becomes namespace n1 { void f(); } // namespace n1 Options ShortNamespaceLines Requires the closing brace of the namespace definition to be followed by a closing comment if the body of the namespace has more than ShortNamespaceLines lines of code. The value is an un- signed integer that defaults to 1U. SpacesBeforeComments An unsigned integer specifying the number of spaces before the comment closing a namespace definition. Default is 1U. llvm-prefer-isa-or-dyn-cast-in-conditionals Looks at conditionals and finds and replaces cases of cast<>, which will assert rather than return a null pointer, and dyn_cast<> where the return value is not captured. Additionally, finds and replaces cases that match the pattern var && isa<X>(var), where var is evaluated twice. // Finds these: if (auto x = cast<X>(y)) {} // is replaced by: if (auto x = dyn_cast<X>(y)) {} if (cast<X>(y)) {} // is replaced by: if (isa<X>(y)) {} if (dyn_cast<X>(y)) {} // is replaced by: if (isa<X>(y)) {} if (var && isa<T>(var)) {} // is replaced by: if (isa_and_nonnull<T>(var.foo())) {} // Other cases are ignored, e.g.: if (auto f = cast<Z>(y)->foo()) {} if (cast<Z>(y)->foo()) {} if (X.cast(y)) {} llvm-prefer-register-over-unsigned Finds historical use of unsigned to hold vregs and physregs and rewrites them to use Register. Currently this works by finding all variables of unsigned integer type whose initializer begins with an implicit cast from Register to un- signed. void example(MachineOperand &MO) { unsigned Reg = MO.getReg(); ... } becomes: void example(MachineOperand &MO) { Register Reg = MO.getReg(); ... } llvm-qualified-auto The llvm-qualified-auto check is an alias, please see readability-qualified-auto for more information. llvm-twine-local Looks for local Twine variables which are prone to use after frees and should be generally avoided. static Twine Moo = Twine("bark") + "bah"; // becomes static std::string Moo = (Twine("bark") + "bah").str(); llvmlibc-callee-namespace Checks all calls resolve to functions within correct namespace. // Implementation inside the LIBC_NAMESPACE namespace. // Correct if: // - LIBC_NAMESPACE is a macro // - LIBC_NAMESPACE expansion starts with `__llvm_libc` namespace LIBC_NAMESPACE { // Allow calls with the fully qualified name. LIBC_NAMESPACE::strlen("hello"); // Allow calls to compiler provided functions. (void)__builtin_abs(-1); // Bare calls are allowed as long as they resolve to the correct namespace. strlen("world"); // Disallow calling into functions in the global namespace. ::strlen("!"); } // namespace LIBC_NAMESPACE llvmlibc-implementation-in-namespace Checks that all declarations in the llvm-libc implementation are within the correct namespace. // Implementation inside the LIBC_NAMESPACE namespace. // Correct if: // - LIBC_NAMESPACE is a macro // - LIBC_NAMESPACE expansion starts with `__llvm_libc` namespace LIBC_NAMESPACE { void LLVM_LIBC_ENTRYPOINT(strcpy)(char *dest, const char *src) {} // Namespaces within LIBC_NAMESPACE namespace are allowed. namespace inner { int localVar = 0; } // Functions with C linkage are allowed. extern "C" void str_fuzz() {} } // Incorrect: implementation not in the LIBC_NAMESPACE namespace. void LLVM_LIBC_ENTRYPOINT(strcpy)(char *dest, const char *src) {} // Incorrect: outer most namespace is not the LIBC_NAMESPACE macro. namespace something_else { void LLVM_LIBC_ENTRYPOINT(strcpy)(char *dest, const char *src) {} } // Incorrect: outer most namespace expansion does not start with `__llvm_libc`. #define LIBC_NAMESPACE custom_namespace namespace LIBC_NAMESPACE { void LLVM_LIBC_ENTRYPOINT(strcpy)(char *dest, const char *src) {} } llvmlibc-inline-function-decl Checks that all implicitly and explicitly inline functions in header files are tagged with the LIBC_INLINE macro, except for functions im- plicit to classes or deleted functions. See the libc style guide for more information about this macro. llvmlibc-restrict-system-libc-headers Finds includes of system libc headers not provided by the compiler within llvm-libc implementations. #include <stdio.h> // Not allowed because it is part of system libc. #include <stddef.h> // Allowed because it is provided by the compiler. #include "internal/stdio.h" // Allowed because it is NOT part of system libc. This check is necessary because accidentally including system libc headers can lead to subtle and hard to detect bugs. For example con- sider a system libc whose dirent struct has slightly different field ordering than llvm-libc. While this will compile successfully, this can cause issues during runtime because they are ABI incompatible. Options Includes A string containing a comma separated glob list of allowed in- clude filenames. Similar to the -checks glob list for running clang-tidy itself, the two wildcard characters are * and -, to include and exclude globs, respectively. The default is -*, which disallows all includes. This can be used to allow known safe includes such as Linux de- velopment headers. See portability-restrict-system-includes for more details. misc-confusable-identifiers Warn about confusable identifiers, i.e. identifiers that are visually close to each other, but use different Unicode characters. This detects a potential attack described in CVE-2021-42574. Example: int fo; // Initial character is U+0066 (LATIN SMALL LETTER F). int o; // Initial character is U+1D41F (MATHEMATICAL BOLD SMALL F) not U+0066 (LATIN SMALL LETTER F). misc-const-correctness This check implements detection of local variables which could be de- clared as const but are not. Declaring variables as const is required or recommended by many coding guidelines, such as: ES.25 from the C++ Core Guidelines and AUTOSAR C++14 Rule A7-1-1 (6.7.1 Specifiers). Please note that this check's analysis is type-based only. Variables that are not modified but used to create a non-const handle that might escape the scope are not diagnosed as potential const. // Declare a variable, which is not ``const`` ... int i = 42; // but use it as read-only. This means that `i` can be declared ``const``. int result = i * i; // Before transformation int const result = i * i; // After transformation The check can analyze values, pointers and references but not (yet) pointees: // Normal values like built-ins or objects. int potential_const_int = 42; // Before transformation int const potential_const_int = 42; // After transformation int copy_of_value = potential_const_int; MyClass could_be_const; // Before transformation MyClass const could_be_const; // After transformation could_be_const.const_qualified_method(); // References can be declared const as well. int &reference_value = potential_const_int; // Before transformation int const& reference_value = potential_const_int; // After transformation int another_copy = reference_value; // The similar semantics of pointers are not (yet) analyzed. int *pointer_variable = &potential_const_int; // _NO_ 'const int *pointer_variable' suggestion. int last_copy = *pointer_variable; The automatic code transformation is only applied to variables that are declared in single declarations. You may want to prepare your code base with readability-isolate-declaration first. Note that there is the check cppcoreguidelines-avoid-non-const-global-variables to enforce const correctness on all globals. Known Limitations The check does not run on C code. The check will not analyze templated variables or variables that are instantiation dependent. Different instantiations can result in dif- ferent const correctness properties and in general it is not possible to find all instantiations of a template. The template might be used differently in an independent translation unit. Pointees can not be analyzed for constness yet. The following code shows this limitation. // Declare a variable that will not be modified. int constant_value = 42; // Declare a pointer to that variable, that does not modify either, but misses 'const'. // Could be 'const int *pointer_to_constant = &constant_value;' int *pointer_to_constant = &constant_value; // Usage: int result = 520 * 120 * (*pointer_to_constant); This limitation affects the capability to add const to methods which is not possible, too. Options AnalyzeValues (default = true) Enable or disable the analysis of ordinary value variables, like int i = 42; // Warning int i = 42; // No warning int const i = 42; // Warning int a[] = {42, 42, 42}; // No warning int const a[] = {42, 42, 42}; AnalyzeReferences (default = true) Enable or disable the analysis of reference variables, like int &ref = i; int i = 42; // Warning int& ref = i; // No warning int const& ref = i; WarnPointersAsValues (default = false) This option enables the suggestion for const of the pointer it- self. Pointer values have two possibilities to be const, the pointer and the value pointing to. int value = 42; // Warning const int * pointer_variable = &value; // No warning const int *const pointer_variable = &value; TransformValues (default = true) Provides fixit-hints for value types that automatically add const if its a single declaration. // Before int value = 42; // After int const value = 42; // Before int a[] = {42, 42, 42}; // After int const a[] = {42, 42, 42}; // Result is modified later in its life-time. No diagnostic and fixit hint will be emitted. int result = value * 3; result -= 10; TransformReferences (default = true) Provides fixit-hints for reference types that automatically add const if its a single declaration. // This variable could still be a constant. But because there is a non-const reference to // it, it can not be transformed (yet). int value = 42; // The reference 'ref_value' is not modified and can be made 'const int &ref_value = value;' // Before int &ref_value = value; // After int const &ref_value = value; // Result is modified later in its life-time. No diagnostic and fixit hint will be emitted. int result = ref_value * 3; result -= 10; TransformPointersAsValues (default = false) Provides fixit-hints for pointers if their pointee is not changed. This does not analyze if the value-pointed-to is un- changed! Requires 'WarnPointersAsValues' to be 'true'. int value = 42; // Before const int * pointer_variable = &value; // After const int *const pointer_variable = &value; // Before const int * a[] = {&value, &value}; // After const int *const a[] = {&value, &value}; // Before int *ptr_value = &value; // After int *const ptr_value = &value; int result = 100 * (*ptr_value); // Does not modify the pointer itself. // This modification of the pointee is still allowed and not diagnosed. *ptr_value = 0; // The following pointer may not become a 'int *const'. int *changing_pointee = &value; changing_pointee = &result; misc-coroutine-hostile-raii Detects when objects of certain hostile RAII types persists across sus- pension points in a coroutine. Such hostile types include scoped-lock- able types and types belonging to a configurable denylist. Some objects require that they be destroyed on the same thread that created them. Traditionally this requirement was often phrased as "must be a local variable", under the assumption that local variables always work this way. However this is incorrect with C++20 coroutines, since an intervening co_await may cause the coroutine to suspend and later be resumed on another thread. The lifetime of an object that requires being destroyed on the same thread must not encompass a co_await or co_yield point. If you cre- ate/destroy an object, you must do so without allowing the coroutine to suspend in the meantime. Following types are considered as hostile: • Scoped-lockable types: A scoped-lockable object persisting across a suspension point is problematic as the lock held by this object could be unlocked by a different thread. This would be undefined behaviour. This includes all types annotated with the scoped_lockable attribute. • Types belonging to a configurable denylist. // Call some async API while holding a lock. task coro() { const std::lock_guard l(&mu_); // Oops! The async Bar function may finish on a different // thread from the one that created the lock_guard (and called // Mutex::Lock). After suspension, Mutex::Unlock will be called on the wrong thread. co_await Bar(); } Options RAIITypesList A semicolon-separated list of qualified types which should not be allowed to persist across suspension points. Eg: my::lock- able; a::b;::my::other::lockable; The default value of this op- tion is "std::lock_guard;std::scoped_lock". AllowedAwaitablesList A semicolon-separated list of qualified types of awaitables types which can be safely awaited while having hostile RAII ob- jects in scope. co_await-ing an expression of awaitable type is considered safe if the awaitable type is part of this list. RAII objects per- sisting across such a co_await expression are considered safe and hence are not flagged. Example usage: // Consider option AllowedAwaitablesList = "safe_awaitable" struct safe_awaitable { bool await_ready() noexcept { return false; } void await_suspend(std::coroutine_handle<>) noexcept {} void await_resume() noexcept {} }; auto wait() { return safe_awaitable{}; } task coro() { // This persists across both the co_await's but is not flagged // because the awaitable is considered safe to await on. const std::lock_guard l(&mu_); co_await safe_awaitable{}; co_await wait(); } Eg: my::safe::awaitable;other::awaitable The default value of this option is empty string "". misc-definitions-in-headers Finds non-extern non-inline function and variable definitions in header files, which can lead to potential ODR violations in case these headers are included from multiple translation units. // Foo.h int a = 1; // Warning: variable definition. extern int d; // OK: extern variable. namespace N { int e = 2; // Warning: variable definition. } // Warning: variable definition. const char* str = "foo"; // OK: internal linkage variable definitions are ignored for now. // Although these might also cause ODR violations, we can be less certain and // should try to keep the false-positive rate down. static int b = 1; const int c = 1; const char* const str2 = "foo"; constexpr int k = 1; namespace { int x = 1; } // Warning: function definition. int g() { return 1; } // OK: inline function definition is allowed to be defined multiple times. inline int e() { return 1; } class A { public: int f1() { return 1; } // OK: implicitly inline member function definition is allowed. int f2(); static int d; }; // Warning: not an inline member function definition. int A::f2() { return 1; } // OK: class static data member declaration is allowed. int A::d = 1; // OK: function template is allowed. template<typename T> T f3() { T a = 1; return a; } // Warning: full specialization of a function template is not allowed. template <> int f3() { int a = 1; return a; } template <typename T> struct B { void f1(); }; // OK: member function definition of a class template is allowed. template <typename T> void B<T>::f1() {} class CE { constexpr static int i = 5; // OK: inline variable definition. }; inline int i = 5; // OK: inline variable definition. constexpr int f10() { return 0; } // OK: constexpr function implies inline. // OK: C++14 variable templates are inline. template <class T> constexpr T pi = T(3.1415926L); When clang-tidy is invoked with the --fix-notes option, this check pro- vides fixes that automatically add the inline keyword to discovered functions. Please note that the addition of the inline keyword to vari- ables is not currently supported by this check. Options HeaderFileExtensions Note: this option is deprecated, it will be removed in clang-tidy version 19. Please use the global configuration op- tion HeaderFileExtensions. A comma-separated list of filename extensions of header files (the filename extensions should not include "." prefix). Default is "h,hh,hpp,hxx". For header files without an extension, use an empty string (if there are no other desired extensions) or leave an empty element in the list. E.g., "h,hh,hpp,hxx," (note the trailing comma). UseHeaderFileExtension Note: this option is deprecated, it will be removed in clang-tidy version 19. The check will unconditionally use the global option HeaderFileExtensions. When true, the check will use the file extension to distinguish header files. Default is true. misc-header-include-cycle Check detects cyclic #include dependencies between user-defined head- ers. // Header A.hpp #pragma once #include "B.hpp" // Header B.hpp #pragma once #include "C.hpp" // Header C.hpp #pragma once #include "A.hpp" // Include chain: A->B->C->A Header files are a crucial part of many C++ programs as they provide a way to organize declarations and definitions shared across multiple source files. However, header files can also create problems when they become entangled in complex dependency cycles. Such cycles can cause issues with compilation times, unnecessary rebuilds, and make it harder to understand the overall structure of the code. To address these issues, a check has been developed to detect cyclic dependencies between header files, also known as "include cycles". An include cycle occurs when a header file A includes header file B, and B (or any subsequent included header file) includes back header file A, resulting in a circular dependency cycle. This check operates at the preprocessor level and specifically analyzes user-defined headers and their dependencies. It focuses solely on de- tecting include cycles while disregarding other types or function de- pendencies. This specialized analysis helps identify and prevent is- sues related to header file organization. By detecting include cycles early in the development process, develop- ers can identify and resolve these issues before they become more dif- ficult and time-consuming to fix. This can lead to faster compile times, improved code quality, and a more maintainable codebase overall. Additionally, by ensuring that header files are organized in a way that avoids cyclic dependencies, developers can make their code easier to understand and modify over time. It's worth noting that only user-defined headers their dependencies are analyzed, System includes such as standard library headers and third-party library headers are excluded. System includes are usually well-designed and free of include cycles, and ignoring them helps to focus on potential issues within the project's own codebase. This limi- tation doesn't diminish the ability to detect #include cycles within the analyzed code. Developers should carefully review any warnings or feedback provided by this solution. While the analysis aims to identify and prevent include cycles, there may be situations where exceptions or modifications are necessary. It's important to exercise judgment and consider the spe- cific context of the codebase when making adjustments. Options IgnoredFilesList Provides a way to exclude specific files/headers from the warn- ings raised by a check. This can be achieved by specifying a semicolon-separated list of regular expressions or filenames. This option can be used as an alternative to //NOLINT when using it is not possible. The default value of this option is an empty string, indicating that no files are ignored by default. misc-include-cleaner Checks for unused and missing includes. Generates findings only for the main file of a translation unit. Findings correspond to https://clangd.llvm.org/design/include-cleaner. Example: // foo.h class Foo{}; // bar.h #include "baz.h" class Bar{}; // baz.h class Baz{}; // main.cc #include "bar.h" // OK: uses class Bar from bar.h #include "foo.h" // warning: unused include "foo.h" Bar bar; Baz baz; // warning: missing include "baz.h" Options IgnoreHeaders A semicolon-separated list of regexes to disable insertion/re- moval of header files that match this regex as a suffix. E.g., foo/.* disables insertion/removal for all headers under the di- rectory foo. By default, no headers will be ignored. DeduplicateFindings A boolean that controls whether the check should deduplicate findings for the same symbol. Defaults to true. misc-misleading-bidirectional Warn about unterminated bidirectional unicode sequence, detecting po- tential attack as described in the Trojan Source attack. Example: #include <iostream> int main() { bool isAdmin = false; /* } if (isAdmin) begin admins only */ std::cout << "You are an admin.\n"; /* end admins only { */ return 0; } misc-misleading-identifier Finds identifiers that contain Unicode characters with right-to-left direction, which can be confusing as they may change the understanding of a whole statement line, as described in Trojan Source. An example of such misleading code follows: #include <stdio.h> short int = (short int)0; short int = (short int)12345; int main() { int = ; // a local variable, set to zero? printf(" is %d\n", ); printf(" is %d\n", ); } misc-misplaced-const This check diagnoses when a const qualifier is applied to a typedef/ using to a pointer type rather than to the pointee, because such con- structs are often misleading to developers because the const applies to the pointer rather than the pointee. For instance, in the following code, the resulting type is int * const rather than const int *: typedef int *int_ptr; void f(const int_ptr ptr) { *ptr = 0; // potentially quite unexpectedly the int can be modified here ptr = 0; // does not compile } The check does not diagnose when the underlying typedef/using type is a pointer to a const type or a function pointer type. This is because the const qualifier is less likely to be mistaken because it would be re- dundant (or disallowed) on the underlying pointee type. misc-new-delete-overloads cert-dcl54-cpp redirects here as an alias for this check. The check flags overloaded operator new() and operator delete() func- tions that do not have a corresponding free store function defined within the same scope. For instance, the check will flag a class im- plementation of a non-placement operator new() when the class does not also define a non-placement operator delete() function as well. The check does not flag implicitly-defined operators, deleted or pri- vate operators, or placement operators. This check corresponds to CERT C++ Coding Standard rule DCL54-CPP. Overload allocation and deallocation functions as a pair in the same scope. misc-no-recursion Finds strongly connected functions (by analyzing the call graph for SCC's (Strongly Connected Components) that are loops), diagnoses each function in the cycle, and displays one example of a possible call graph loop (recursion). References: • CERT C++ Coding Standard rule DCL56-CPP. Avoid cycles during initial- ization of static objects. • JPL Institutional Coding Standard for the C Programming Language (JPL DOCID D-60411) rule 2.4 Do not use direct or indirect recursion. • OpenCL Specification, Version 1.2 rule 6.9 Restrictions: i. Recursion is not supported.. Limitations: • The check does not handle calls done through function pointers • The check does not handle C++ destructors misc-non-copyable-objects cert-fio38-c redirects here as an alias for this check. The check flags dereferences and non-pointer declarations of objects that are not meant to be passed by value, such as C FILE objects or POSIX pthread_mutex_t objects. This check corresponds to CERT C++ Coding Standard rule FIO38-C. Do not copy a FILE object. misc-non-private-member-variables-in-classes cppcoreguidelines-non-private-member-variables-in-classes redirects here as an alias for this check. Finds classes that contain non-static data members in addition to user-declared non-static member functions and diagnose all data members declared with a non-public access specifier. The data members should be declared as private and accessed through member functions instead of exposed to derived classes or class consumers. Options IgnoreClassesWithAllMemberVariablesBeingPublic Allows to completely ignore classes if all the member variables in that class a declared with a public access specifier. IgnorePublicMemberVariables Allows to ignore (not diagnose) all the member variables de- clared with a public access specifier. misc-redundant-expression Detect redundant expressions which are typically errors due to copy-paste. Depending on the operator expressions may be • redundant, • always true, • always false, • always a constant (zero or one). Examples: ((x+1) | (x+1)) // (x+1) is redundant (p->x == p->x) // always true (p->x < p->x) // always false (speed - speed + 1 == 12) // speed - speed is always zero misc-static-assert cert-dcl03-c redirects here as an alias for this check. Replaces assert() with static_assert() if the condition is evaluable at compile time. The condition of static_assert() is evaluated at compile time which is safer and more efficient. misc-throw-by-value-catch-by-reference cert-err09-cpp redirects here as an alias for this check. cert-err61-cpp redirects here as an alias for this check. Finds violations of the rule "Throw by value, catch by reference" pre- sented for example in "C++ Coding Standards" by H. Sutter and A. Alexandrescu, as well as the CERT C++ Coding Standard rule ERR61-CPP. Catch exceptions by lvalue reference. Exceptions: • Throwing string literals will not be flagged despite being a pointer. They are not susceptible to slicing and the usage of string literals is idiomatic. • Catching character pointers (char, wchar_t, unicode character types) will not be flagged to allow catching string literals. • Moved named values will not be flagged as not throwing an anonymous temporary. In this case we can be sure that the user knows that the object can't be accessed outside catch blocks handling the error. • Throwing function parameters will not be flagged as not throw- ing an anonymous temporary. This allows helper functions for throwing. • Re-throwing caught exception variables will not be flagged as not throwing an anonymous temporary. Although this can usually be done by just writing throw; it happens often enough in real code. Options CheckThrowTemporaries Triggers detection of violations of the CERT recommendation ERR09-CPP. Throw anonymous temporaries. Default is true. WarnOnLargeObject Also warns for any large, trivial object caught by value. Catch- ing a large object by value is not dangerous but affects the performance negatively. The maximum size of an object allowed to be caught without warning can be set using the MaxSize option. Default is false. MaxSize Determines the maximum size of an object allowed to be caught without warning. Only applicable if WarnOnLargeObject is set to true. If the option is set by the user to std::numeric_lim- its<uint64_t>::max() then it reverts to the default value. De- fault is the size of size_t. misc-unconventional-assign-operator Finds declarations of assign operators with the wrong return and/or ar- gument types and definitions with good return type but wrong return statements. • The return type must be Class&. • The assignment may be from the class type by value, const lvalue reference, non-const rvalue reference, or from a completely dif- ferent type (e.g. int). • Private and deleted operators are ignored. • The operator must always return *this. This check implements AUTOSAR C++14 Rule A13-2-1. misc-uniqueptr-reset-release Find and replace unique_ptr::reset(release()) with std::move(). Example: std::unique_ptr<Foo> x, y; x.reset(y.release()); -> x = std::move(y); If y is already rvalue, std::move() is not added. x and y can also be std::unique_ptr<Foo>*. Options IncludeStyle A string specifying which include-style is used, llvm or google. Default is llvm. misc-unused-alias-decls Finds unused namespace alias declarations. namespace my_namespace { class C {}; } namespace unused_alias = ::my_namespace; misc-unused-parameters Finds unused function parameters. Unused parameters may signify a bug in the code (e.g. when a different parameter is used instead). The sug- gested fixes either comment parameter name out or remove the parameter completely, if all callers of the function are in the same translation unit and can be updated. The check is similar to the -Wunused-parameter compiler diagnostic and can be used to prepare a codebase to enabling of that diagnostic. By default the check is more permissive (see StrictMode). void a(int i) { /*some code that doesn't use `i`*/ } // becomes void a(int /*i*/) { /*some code that doesn't use `i`*/ } static void staticFunctionA(int i); static void staticFunctionA(int i) { /*some code that doesn't use `i`*/ } // becomes static void staticFunctionA() static void staticFunctionA() { /*some code that doesn't use `i`*/ } Options StrictMode When false (default value), the check will ignore trivially un- used parameters, i.e. when the corresponding function has an empty body (and in case of constructors - no constructor ini- tializers). When the function body is empty, an unused parameter is unlikely to be unnoticed by a human reader, and there's basi- cally no place for a bug to hide. IgnoreVirtual Determines whether virtual method parameters should be in- spected. Set to true to ignore them. Default is false. misc-unused-using-decls Finds unused using declarations. Unused using` declarations in header files will not be diagnosed since these using declarations are part of the header's public API. Allowed header file extensions can be configured via the HeaderFileExtensions option (see below). Example: // main.cpp namespace n { class C; } using n::C; // Never actually used. Options HeaderFileExtensions Note: this option is deprecated, it will be removed in clang-tidy version 19. Please use the global configuration op- tion HeaderFileExtensions. A semicolon-separated list of filename extensions of header files (the filename extensions should not include "." prefix). Default is "h,hh,hpp,hxx". For extension-less header files, use an empty string or leave an empty string between "," if there are other filename extensions. misc-use-anonymous-namespace Finds instances of static functions or variables declared at global scope that could instead be moved into an anonymous namespace. Anonymous namespaces are the "superior alternative" according to the C++ Standard. static was proposed for deprecation, but later un-depre- cated to keep C compatibility [1]. static is an overloaded term with different meanings in different contexts, so it can create confusion. The following uses of static will not be diagnosed: • Functions or variables in header files, since anonymous namespaces in headers is considered an antipattern. Allowed header file extensions can be configured via the HeaderFileExtensions option (see below). • const or constexpr variables, since they already have implicit inter- nal linkage in C++. Examples: // Bad static void foo(); static int x; // Good namespace { void foo(); int x; } // namespace Options HeaderFileExtensions Note: this option is deprecated, it will be removed in clang-tidy version 19. Please use the global configuration op- tion HeaderFileExtensions. A semicolon-separated list of filename extensions of header files (the filename extensions should not include "." prefix). Default is ";h;hh;hpp;hxx". For extension-less header files, using an empty string or leaving an empty string between ";" if there are other filename extensions. [1] Undeprecating static modernize-avoid-bind The check finds uses of std::bind and boost::bind and replaces them with lambdas. Lambdas will use value-capture unless reference capture is explicitly requested with std::ref or boost::ref. It supports arbitrary callables including member functions, function objects, and free functions, and all variations thereof. Anything that you can pass to the first argument of bind should be diagnosable. Cur- rently, the only known case where a fix-it is unsupported is when the same placeholder is specified multiple times in the parameter list. Given: int add(int x, int y) { return x + y; } Then: void f() { int x = 2; auto clj = std::bind(add, x, _1); } is replaced by: void f() { int x = 2; auto clj = [=](auto && arg1) { return add(x, arg1); }; } std::bind can be hard to read and can result in larger object files and binaries due to type information that will not be produced by equiva- lent lambdas. Options PermissiveParameterList If the option is set to true, the check will append auto&&... to the end of every placeholder parameter list. Without this, it is possible for a fix-it to perform an incorrect transformation in the case where the result of the bind is used in the context of a type erased functor such as std::function which allows mis- matched arguments. For example: int add(int x, int y) { return x + y; } int foo() { std::function<int(int,int)> ignore_args = std::bind(add, 2, 2); return ignore_args(3, 3); } is valid code, and returns 4. The actual values passed to ignore_args are simply ignored. Without PermissiveParameterList, this would be transformed into int add(int x, int y) { return x + y; } int foo() { std::function<int(int,int)> ignore_args = [] { return add(2, 2); } return ignore_args(3, 3); } which will not compile, since the lambda does not contain an operator() that accepts 2 arguments. With permissive parameter list, it instead generates int add(int x, int y) { return x + y; } int foo() { std::function<int(int,int)> ignore_args = [](auto&&...) { return add(2, 2); } return ignore_args(3, 3); } which is correct. This check requires using C++14 or higher to run. modernize-avoid-c-arrays cppcoreguidelines-avoid-c-arrays redirects here as an alias for this check. hicpp-avoid-c-arrays redirects here as an alias for this check. Finds C-style array types and recommend to use std::array<> / std::vec- tor<>. All types of C arrays are diagnosed. However, fix-it are potentially dangerous in header files and are therefore not emitted right now. int a[] = {1, 2}; // warning: do not declare C-style arrays, use std::array<> instead int b[1]; // warning: do not declare C-style arrays, use std::array<> instead void foo() { int c[b[0]]; // warning: do not declare C VLA arrays, use std::vector<> instead } template <typename T, int Size> class array { T d[Size]; // warning: do not declare C-style arrays, use std::array<> instead int e[1]; // warning: do not declare C-style arrays, use std::array<> instead }; array<int[4], 2> d; // warning: do not declare C-style arrays, use std::array<> instead using k = int[4]; // warning: do not declare C-style arrays, use std::array<> instead However, the extern "C" code is ignored, since it is common to share such headers between C code, and C++ code. // Some header extern "C" { int f[] = {1, 2}; // not diagnosed int j[1]; // not diagnosed inline void bar() { { int j[j[0]]; // not diagnosed } } } Similarly, the main() function is ignored. Its second and third parame- ters can be either char* argv[] or char** argv, but cannot be std::ar- ray<>. modernize-concat-nested-namespaces Checks for use of nested namespaces such as namespace a { namespace b { ... } } and suggests changing to the more concise syntax introduced in C++17: namespace a::b { ... }. Inline namespaces are not modified. For example: namespace n1 { namespace n2 { void t(); } } namespace n3 { namespace n4 { namespace n5 { void t(); } } namespace n6 { namespace n7 { void t(); } } } // in c++20 namespace n8 { inline namespace n9 { void t(); } } Will be modified to: namespace n1::n2 { void t(); } namespace n3 { namespace n4::n5 { void t(); } namespace n6::n7 { void t(); } } // in c++20 namespace n8::inline n9 { void t(); } modernize-deprecated-headers Some headers from C library were deprecated in C++ and are no longer welcome in C++ codebases. Some have no effect in C++. For more details refer to the C++ 14 Standard [depr.c.headers] section. This check replaces C standard library headers with their C++ alterna- tives and removes redundant ones. // C++ source file... #include <assert.h> #include <stdbool.h> // becomes #include <cassert> // No 'stdbool.h' here. Important note: the Standard doesn't guarantee that the C++ headers de- clare all the same functions in the global namespace. The check in its current form can break the code that uses library symbols from the global namespace. • <assert.h> • <complex.h> • <ctype.h> • <errno.h> • <fenv.h> // deprecated since C++11 • <float.h> • <inttypes.h> • <limits.h> • <locale.h> • <math.h> • <setjmp.h> • <signal.h> • <stdarg.h> • <stddef.h> • <stdint.h> • <stdio.h> • <stdlib.h> • <string.h> • <tgmath.h> // deprecated since C++11 • <time.h> • <uchar.h> // deprecated since C++11 • <wchar.h> • <wctype.h> If the specified standard is older than C++11 the check will only re- place headers deprecated before C++11, otherwise -- every header that appeared in the previous list. These headers don't have effect in C++: • <iso646.h> • <stdalign.h> • <stdbool.h> The checker ignores include directives within extern "C" { ... } blocks, since a library might want to expose some API for C and C++ li- braries. // C++ source file... extern "C" { #include <assert.h> // Left intact. #include <stdbool.h> // Left intact. } Options CheckHeaderFile clang-tidy cannot know if the header file included by the cur- rently analyzed C++ source file is not included by any other C source files. Hence, to omit false-positives and wrong fixit-hints, we ignore emitting reports into header files. One can set this option to true if they know that the header files in the project are only used by C++ source file. Default is false. modernize-deprecated-ios-base-aliases Detects usage of the deprecated member types of std::ios_base and re- places those that have a non-deprecated equivalent. +--------------------------+-------------------------+ | Deprecated member type | Replacement | +--------------------------+-------------------------+ | std::ios_base::io_state | std::ios_base::iostate | +--------------------------+-------------------------+ | std::ios_base::open_mode | std::ios_base::openmode | +--------------------------+-------------------------+ | std::ios_base::seek_dir | std::ios_base::seekdir | +--------------------------+-------------------------+ | std::ios_base::streamoff | | +--------------------------+-------------------------+ | std::ios_base::streampos | | +--------------------------+-------------------------+ modernize-loop-convert This check converts for(...; ...; ...) loops to use the new range-based loops in C++11. Three kinds of loops can be converted: • Loops over statically allocated arrays. • Loops over containers, using iterators. • Loops over array-like containers, using operator[] and at(). MinConfidence option risky In loops where the container expression is more complex than just a reference to a declared expression (a variable, function, enum, etc.), and some part of it appears elsewhere in the loop, we lower our confi- dence in the transformation due to the increased risk of changing se- mantics. Transformations for these loops are marked as risky, and thus will only be converted if the minimum required confidence level is set to risky. int arr[10][20]; int l = 5; for (int j = 0; j < 20; ++j) int k = arr[l][j] + l; // using l outside arr[l] is considered risky for (int i = 0; i < obj.getVector().size(); ++i) obj.foo(10); // using 'obj' is considered risky See Range-based loops evaluate end() only once for an example of an in- correct transformation when the minimum required confidence level is set to risky. reasonable (Default) If a loop calls .end() or .size() after each iteration, the transforma- tion for that loop is marked as reasonable, and thus will be converted if the required confidence level is set to reasonable (default) or lower. // using size() is considered reasonable for (int i = 0; i < container.size(); ++i) cout << container[i]; safe Any other loops that do not match the above criteria to be marked as risky or reasonable are marked safe, and thus will be converted if the required confidence level is set to safe or lower. int arr[] = {1,2,3}; for (int i = 0; i < 3; ++i) cout << arr[i]; Example Original: const int N = 5; int arr[] = {1,2,3,4,5}; vector<int> v; v.push_back(1); v.push_back(2); v.push_back(3); // safe conversion for (int i = 0; i < N; ++i) cout << arr[i]; // reasonable conversion for (vector<int>::iterator it = v.begin(); it != v.end(); ++it) cout << *it; // reasonable conversion for (vector<int>::iterator it = begin(v); it != end(v); ++it) cout << *it; // reasonable conversion for (vector<int>::iterator it = std::begin(v); it != std::end(v); ++it) cout << *it; // reasonable conversion for (int i = 0; i < v.size(); ++i) cout << v[i]; // reasonable conversion for (int i = 0; i < size(v); ++i) cout << v[i]; After applying the check with minimum confidence level set to reason- able (default): const int N = 5; int arr[] = {1,2,3,4,5}; vector<int> v; v.push_back(1); v.push_back(2); v.push_back(3); // safe conversion for (auto & elem : arr) cout << elem; // reasonable conversion for (auto & elem : v) cout << elem; // reasonable conversion for (auto & elem : v) cout << elem; Reverse Iterator Support The converter is also capable of transforming iterator loops which use rbegin and rend for looping backwards over a container. Out of the box this will automatically happen in C++20 mode using the ranges library, however the check can be configured to work without C++20 by specifying a function to reverse a range and optionally the header file where that function lives. UseCxx20ReverseRanges When set to true convert loops when in C++20 or later mode using std::ranges::reverse_view. Default value is true. MakeReverseRangeFunction Specify the function used to reverse an iterator pair, the func- tion should accept a class with rbegin and rend methods and re- turn a class with begin and end methods that call the rbegin and rend methods respectively. Common examples are ranges::re- verse_view and llvm::reverse. Default value is an empty string. MakeReverseRangeHeader Specifies the header file where MakeReverseRangeFunction is de- clared. For the previous examples this option would be set to range/v3/view/reverse.hpp and llvm/ADT/STLExtras.h respectively. If this is an empty string and MakeReverseRangeFunction is set, the check will proceed on the assumption that the function is already available in the translation unit. This can be wrapped in angle brackets to signify to add the include as a system in- clude. Default value is an empty string. IncludeStyle A string specifying which include-style is used, llvm or google. Default is llvm. Limitations There are certain situations where the tool may erroneously perform transformations that remove information and change semantics. Users of the tool should be aware of the behavior and limitations of the check outlined by the cases below. Comments inside loop headers Comments inside the original loop header are ignored and deleted when transformed. for (int i = 0; i < N; /* This will be deleted */ ++i) { } Range-based loops evaluate end() only once The C++11 range-based for loop calls .end() only once during the ini- tialization of the loop. If in the original loop .end() is called after each iteration the semantics of the transformed loop may differ. // The following is semantically equivalent to the C++11 range-based for loop, // therefore the semantics of the header will not change. for (iterator it = container.begin(), e = container.end(); it != e; ++it) { } // Instead of calling .end() after each iteration, this loop will be // transformed to call .end() only once during the initialization of the loop, // which may affect semantics. for (iterator it = container.begin(); it != container.end(); ++it) { } As explained above, calling member functions of the container in the body of the loop is considered risky. If the called member function modifies the container the semantics of the converted loop will differ due to .end() being called only once. bool flag = false; for (vector<T>::iterator it = vec.begin(); it != vec.end(); ++it) { // Add a copy of the first element to the end of the vector. if (!flag) { // This line makes this transformation 'risky'. vec.push_back(*it); flag = true; } cout << *it; } The original code above prints out the contents of the container in- cluding the newly added element while the converted loop, shown below, will only print the original contents and not the newly added element. bool flag = false; for (auto & elem : vec) { // Add a copy of the first element to the end of the vector. if (!flag) { // This line makes this transformation 'risky' vec.push_back(elem); flag = true; } cout << elem; } Semantics will also be affected if .end() has side effects. For exam- ple, in the case where calls to .end() are logged the semantics will change in the transformed loop if .end() was originally called after each iteration. iterator end() { num_of_end_calls++; return container.end(); } Overloaded operator->() with side effects Similarly, if operator->() was overloaded to have side effects, such as logging, the semantics will change. If the iterator's operator->() was used in the original loop it will be replaced with <container ele- ment>.<member> instead due to the implicit dereference as part of the range-based for loop. Therefore any side effect of the overloaded op- erator->() will no longer be performed. for (iterator it = c.begin(); it != c.end(); ++it) { it->func(); // Using operator->() } // Will be transformed to: for (auto & elem : c) { elem.func(); // No longer using operator->() } Pointers and references to containers While most of the check's risk analysis is dedicated to determining whether the iterator or container was modified within the loop, it is possible to circumvent the analysis by accessing and modifying the con- tainer through a pointer or reference. If the container were directly used instead of using the pointer or reference the following transformation would have only been applied at the risky level since calling a member function of the container is considered risky. The check cannot identify expressions associated with the container that are different than the one used in the loop header, therefore the transformation below ends up being performed at the safe level. vector<int> vec; vector<int> *ptr = &vec; vector<int> &ref = vec; for (vector<int>::iterator it = vec.begin(), e = vec.end(); it != e; ++it) { if (!flag) { // Accessing and modifying the container is considered risky, but the risk // level is not raised here. ptr->push_back(*it); ref.push_back(*it); flag = true; } } OpenMP As range-based for loops are only available since OpenMP 5, this check should not be used on code with a compatibility requirement of OpenMP prior to version 5. It is intentional that this check does not make any attempts to exclude incorrect diagnostics on OpenMP for loops prior to OpenMP 5. To prevent this check to be applied (and to break) OpenMP for loops but still be applied to non-OpenMP for loops the usage of NOLINT (see Suppressing Undesired Diagnostics) on the specific for loops is recom- mended. modernize-macro-to-enum Replaces groups of adjacent macros with an unscoped anonymous enum. Using an unscoped anonymous enum ensures that everywhere the macro to- ken was used previously, the enumerator name may be safely used. This check can be used to enforce the C++ core guideline Enum.1: Prefer enumerations over macros, within the constraints outlined below. Potential macros for replacement must meet the following constraints: • Macros must expand only to integral literal tokens or expressions of literal tokens. The expression may contain any of the unary opera- tors -, +, ~ or !, any of the binary operators ,, -, +, *, /, %, &, |, ^, <, >, <=, >=, ==, !=, ||, &&, <<, >> or <=>, the ternary opera- tor ?: and its GNU extension. Parenthesized expressions are also recognized. This recognizes most valid expressions. In particular, expressions with the sizeof operator are not recognized. • Macros must be defined on sequential source file lines, or with only comment lines in between macro definitions. • Macros must all be defined in the same source file. • Macros must not be defined within a conditional compilation block. (Conditional include guards are exempt from this constraint.) • Macros must not be defined adjacent to other preprocessor directives. • Macros must not be used in any conditional preprocessing directive. • Macros must not be used as arguments to other macros. • Macros must not be undefined. • Macros must be defined at the top-level, not inside any declaration or definition. Each cluster of macros meeting the above constraints is presumed to be a set of values suitable for replacement by an anonymous enum. From there, a developer can give the anonymous enum a name and continue refactoring to a scoped enum if desired. Comments on the same line as a macro definition or between subsequent macro definitions are pre- served in the output. No formatting is assumed in the provided re- placements, although clang-tidy can optionally format all fixes. WARNING: Initializing expressions are assumed to be valid initializers for an enum. C requires that enum values fit into an int, but this may not be the case for some accepted constant expressions. For instance 1 << 40 will not fit into an int when the size of an int is 32 bits. Examples: #define RED 0xFF0000 #define GREEN 0x00FF00 #define BLUE 0x0000FF #define TM_NONE (-1) // No method selected. #define TM_ONE 1 // Use tailored method one. #define TM_TWO 2 // Use tailored method two. Method two // is preferable to method one. #define TM_THREE 3 // Use tailored method three. becomes enum { RED = 0xFF0000, GREEN = 0x00FF00, BLUE = 0x0000FF }; enum { TM_NONE = (-1), // No method selected. TM_ONE = 1, // Use tailored method one. TM_TWO = 2, // Use tailored method two. Method two // is preferable to method one. TM_THREE = 3 // Use tailored method three. }; modernize-make-shared This check finds the creation of std::shared_ptr objects by explicitly calling the constructor and a new expression, and replaces it with a call to std::make_shared. auto my_ptr = std::shared_ptr<MyPair>(new MyPair(1, 2)); // becomes auto my_ptr = std::make_shared<MyPair>(1, 2); This check also finds calls to std::shared_ptr::reset() with a new ex- pression, and replaces it with a call to std::make_shared. my_ptr.reset(new MyPair(1, 2)); // becomes my_ptr = std::make_shared<MyPair>(1, 2); Options MakeSmartPtrFunction A string specifying the name of make-shared-ptr function. De- fault is std::make_shared. MakeSmartPtrFunctionHeader A string specifying the corresponding header of make-shared-ptr function. Default is memory. IncludeStyle A string specifying which include-style is used, llvm or google. Default is llvm. IgnoreMacros If set to true, the check will not give warnings inside macros. Default is true. IgnoreDefaultInitialization If set to non-zero, the check does not suggest edits that will transform default initialization into value initialization, as this can cause performance regressions. Default is 1. modernize-make-unique This check finds the creation of std::unique_ptr objects by explicitly calling the constructor and a new expression, and replaces it with a call to std::make_unique, introduced in C++14. auto my_ptr = std::unique_ptr<MyPair>(new MyPair(1, 2)); // becomes auto my_ptr = std::make_unique<MyPair>(1, 2); This check also finds calls to std::unique_ptr::reset() with a new ex- pression, and replaces it with a call to std::make_unique. my_ptr.reset(new MyPair(1, 2)); // becomes my_ptr = std::make_unique<MyPair>(1, 2); Options MakeSmartPtrFunction A string specifying the name of make-unique-ptr function. De- fault is std::make_unique. MakeSmartPtrFunctionHeader A string specifying the corresponding header of make-unique-ptr function. Default is <memory>. IncludeStyle A string specifying which include-style is used, llvm or google. Default is llvm. IgnoreMacros If set to true, the check will not give warnings inside macros. Default is true. IgnoreDefaultInitialization If set to non-zero, the check does not suggest edits that will transform default initialization into value initialization, as this can cause performance regressions. Default is 1. modernize-pass-by-value With move semantics added to the language and the standard library up- dated with move constructors added for many types it is now interesting to take an argument directly by value, instead of by const-reference, and then copy. This check allows the compiler to take care of choosing the best way to construct the copy. The transformation is usually beneficial when the calling code passes an rvalue and assumes the move construction is a cheap operation. This short example illustrates how the construction of the value happens: void foo(std::string s); std::string get_str(); void f(const std::string &str) { foo(str); // lvalue -> copy construction foo(get_str()); // prvalue -> move construction } NOTE: Currently, only constructors are transformed to make use of pass-by-value. Contributions that handle other situations are wel- come! Pass-by-value in constructors Replaces the uses of const-references constructor parameters that are copied into class fields. The parameter is then moved with std::move(). Since std::move() is a library function declared in <utility> it may be necessary to add this include. The check will add the include directive when necessary. #include <string> class Foo { public: - Foo(const std::string &Copied, const std::string &ReadOnly) - : Copied(Copied), ReadOnly(ReadOnly) + Foo(std::string Copied, const std::string &ReadOnly) + : Copied(std::move(Copied)), ReadOnly(ReadOnly) {} private: std::string Copied; const std::string &ReadOnly; }; std::string get_cwd(); void f(const std::string &Path) { // The parameter corresponding to 'get_cwd()' is move-constructed. By // using pass-by-value in the Foo constructor we managed to avoid a // copy-construction. Foo foo(get_cwd(), Path); } If the parameter is used more than once no transformation is performed since moved objects have an undefined state. It means the following code will be left untouched: #include <string> void pass(const std::string &S); struct Foo { Foo(const std::string &S) : Str(S) { pass(S); } std::string Str; }; Known limitations A situation where the generated code can be wrong is when the object referenced is modified before the assignment in the init-list through a "hidden" reference. Example: std::string s("foo"); struct Base { Base() { s = "bar"; } }; struct Derived : Base { - Derived(const std::string &S) : Field(S) + Derived(std::string S) : Field(std::move(S)) { } std::string Field; }; void f() { - Derived d(s); // d.Field holds "bar" + Derived d(s); // d.Field holds "foo" } Note about delayed template parsing When delayed template parsing is enabled, constructors part of tem- plated contexts; templated constructors, constructors in class tem- plates, constructors of inner classes of template classes, etc., are not transformed. Delayed template parsing is enabled by default on Win- dows as a Microsoft extension: Clang Compiler User's Manual - Microsoft extensions. Delayed template parsing can be enabled using the -fdelayed-tem- plate-parsing flag and disabled using -fno-delayed-template-parsing. Example: template <typename T> class C { std::string S; public: = // using -fdelayed-template-parsing (default on Windows) = C(const std::string &S) : S(S) {} + // using -fno-delayed-template-parsing (default on non-Windows systems) + C(std::string S) : S(std::move(S)) {} }; SEE ALSO: For more information about the pass-by-value idiom, read: Want Speed? Pass by Value. Options IncludeStyle A string specifying which include-style is used, llvm or google. Default is llvm. ValuesOnly When true, the check only warns about copied parameters that are already passed by value. Default is false. modernize-raw-string-literal This check selectively replaces string literals containing escaped characters with raw string literals. Example: const char *const Quotes{"embedded \"quotes\""}; const char *const Paragraph{"Line one.\nLine two.\nLine three.\n"}; const char *const SingleLine{"Single line.\n"}; const char *const TrailingSpace{"Look here -> \n"}; const char *const Tab{"One\tTwo\n"}; const char *const Bell{"Hello!\a And welcome!"}; const char *const Path{"C:\\Program Files\\Vendor\\Application.exe"}; const char *const RegEx{"\\w\\([a-z]\\)"}; becomes const char *const Quotes{R"(embedded "quotes")"}; const char *const Paragraph{"Line one.\nLine two.\nLine three.\n"}; const char *const SingleLine{"Single line.\n"}; const char *const TrailingSpace{"Look here -> \n"}; const char *const Tab{"One\tTwo\n"}; const char *const Bell{"Hello!\a And welcome!"}; const char *const Path{R"(C:\Program Files\Vendor\Application.exe)"}; const char *const RegEx{R"(\w\([a-z]\))"}; The presence of any of the following escapes can cause the string to be converted to a raw string literal: \\, \', \", \?, and octal or hexa- decimal escapes for printable ASCII characters. A string literal containing only escaped newlines is a common way of writing lines of text output. Introducing physical newlines with raw string literals in this case is likely to impede readability. These string literals are left unchanged. An escaped horizontal tab, form feed, or vertical tab prevents the string literal from being converted. The presence of a horizontal tab, form feed or vertical tab in source code is not visually obvious. DelimiterStem Custom delimiter to escape characters in raw string literals. It is used in the following construction: R"stem_delimiter(con- tents)stem_delimiter". The default value is lit. ReplaceShorterLiterals Controls replacing shorter non-raw string literals with longer raw string literals. Setting this option to true enables the re- placement. The default value is false (shorter literals are not replaced). modernize-redundant-void-arg Find and remove redundant void argument lists. Examples: +----------------------------+-------------------------+ | Initial code | Code with applied fixes | +----------------------------+-------------------------+ | int f(void); | int f(); | +----------------------------+-------------------------+ | int (*f(void))(void); | int (*f())(); | +----------------------------+-------------------------+ | typedef int | typedef int (*f_t())(); | | (*f_t(void))(void); | | +----------------------------+-------------------------+ | void (C::*p)(void); | void (C::*p)(); | +----------------------------+-------------------------+ | C::C(void) {} | C::C() {} | +----------------------------+-------------------------+ | C::~C(void) {} | C::~C() {} | +----------------------------+-------------------------+ modernize-replace-auto-ptr This check replaces the uses of the deprecated class std::auto_ptr by std::unique_ptr (introduced in C++11). The transfer of ownership, done by the copy-constructor and the assignment operator, is changed to match std::unique_ptr usage by using explicit calls to std::move(). Migration example: -void take_ownership_fn(std::auto_ptr<int> int_ptr); +void take_ownership_fn(std::unique_ptr<int> int_ptr); void f(int x) { - std::auto_ptr<int> a(new int(x)); - std::auto_ptr<int> b; + std::unique_ptr<int> a(new int(x)); + std::unique_ptr<int> b; - b = a; - take_ownership_fn(b); + b = std::move(a); + take_ownership_fn(std::move(b)); } Since std::move() is a library function declared in <utility> it may be necessary to add this include. The check will add the include directive when necessary. Known Limitations • If headers modification is not activated or if a header is not al- lowed to be changed this check will produce broken code (compilation error), where the headers' code will stay unchanged while the code using them will be changed. • Client code that declares a reference to an std::auto_ptr coming from code that can't be migrated (such as a header coming from a 3rd party library) will produce a compilation error after migration. This is because the type of the reference will be changed to std::unique_ptr but the type returned by the library won't change, binding a refer- ence to std::unique_ptr from an std::auto_ptr. This pattern doesn't make much sense and usually std::auto_ptr are stored by value (other- wise what is the point in using them instead of a reference or a pointer?). // <3rd-party header...> std::auto_ptr<int> get_value(); const std::auto_ptr<int> & get_ref(); // <calling code (with migration)...> -std::auto_ptr<int> a(get_value()); +std::unique_ptr<int> a(get_value()); // ok, unique_ptr constructed from auto_ptr -const std::auto_ptr<int> & p = get_ptr(); +const std::unique_ptr<int> & p = get_ptr(); // won't compile • Non-instantiated templates aren't modified. template <typename X> void f() { std::auto_ptr<X> p; } // only 'f<int>()' (or similar) will trigger the replacement. Options IncludeStyle A string specifying which include-style is used, llvm or google. Default is llvm. modernize-replace-disallow-copy-and-assign-macro Finds macro expansions of DISALLOW_COPY_AND_ASSIGN(Type) and replaces them with a deleted copy constructor and a deleted assignment operator. Before the delete keyword was introduced in C++11 it was common prac- tice to declare a copy constructor and an assignment operator as pri- vate members. This effectively makes them unusable to the public API of a class. With the advent of the delete keyword in C++11 we can abandon the pri- vate access of the copy constructor and the assignment operator and delete the methods entirely. When running this check on a code like this: class Foo { private: DISALLOW_COPY_AND_ASSIGN(Foo); }; It will be transformed to this: class Foo { private: Foo(const Foo &) = delete; const Foo &operator=(const Foo &) = delete; }; Known Limitations • Notice that the migration example above leaves the private access specification untouched. You might want to run the check modernize-use-equals-delete to get warnings for deleted functions in private sections. Options MacroName A string specifying the macro name whose expansion will be re- placed. Default is DISALLOW_COPY_AND_ASSIGN. See: https://en.cppreference.com/w/cpp/language/function#Deleted_functions modernize-replace-random-shuffle This check will find occurrences of std::random_shuffle and replace it with std::shuffle. In C++17 std::random_shuffle will no longer be available and thus we need to replace it. Below are two examples of what kind of occurrences will be found and two examples of what it will be replaced with. std::vector<int> v; // First example std::random_shuffle(vec.begin(), vec.end()); // Second example std::random_shuffle(vec.begin(), vec.end(), randomFunc); Both of these examples will be replaced with: std::shuffle(vec.begin(), vec.end(), std::mt19937(std::random_device()())); The second example will also receive a warning that randomFunc is no longer supported in the same way as before so if the user wants the same functionality, the user will need to change the implementation of the randomFunc. One thing to be aware of here is that std::random_device is quite ex- pensive to initialize. So if you are using the code in a performance critical place, you probably want to initialize it elsewhere. Another thing is that the seeding quality of the suggested fix is quite poor: std::mt19937 has an internal state of 624 32-bit integers, but is only seeded with a single integer. So if you require higher quality random- ness, you should consider seeding better, for example: std::shuffle(v.begin(), v.end(), []() { std::mt19937::result_type seeds[std::mt19937::state_size]; std::random_device device; std::uniform_int_distribution<typename std::mt19937::result_type> dist; std::generate(std::begin(seeds), std::end(seeds), [&] { return dist(device); }); std::seed_seq seq(std::begin(seeds), std::end(seeds)); return std::mt19937(seq); }()); modernize-return-braced-init-list Replaces explicit calls to the constructor in a return with a braced initializer list. This way the return type is not needlessly duplicated in the function definition and the return statement. Foo bar() { Baz baz; return Foo(baz); } // transforms to: Foo bar() { Baz baz; return {baz}; } modernize-shrink-to-fit Replace copy and swap tricks on shrinkable containers with the shrink_to_fit() method call. The shrink_to_fit() method is more readable and more effective than the copy and swap trick to reduce the capacity of a shrinkable container. Note that, the shrink_to_fit() method is only available in C++11 and up. modernize-type-traits Converts standard library type traits of the form traits<...>::type and traits<...>::value into traits_t<...> and traits_v<...> respectively. For example: std::is_integral<T>::value std::is_same<int, float>::value typename std::add_const<T>::type std::make_signed<unsigned>::type Would be converted into: std::is_integral_v<T> std::is_same_v<int, float> std::add_const_t<T> std::make_signed_t<unsigned> Options IgnoreMacros If true don't diagnose traits defined in macros. Note: Fixes will never be emitted for code inside of macros. #define IS_SIGNED(T) std::is_signed<T>::value Defaults to false. modernize-unary-static-assert The check diagnoses any static_assert declaration with an empty string literal and provides a fix-it to replace the declaration with a sin- gle-argument static_assert declaration. The check is only applicable for C++17 and later code. The following code: void f_textless(int a) { static_assert(sizeof(a) <= 10, ""); } is replaced by: void f_textless(int a) { static_assert(sizeof(a) <= 10); } modernize-use-auto This check is responsible for using the auto type specifier for vari- able declarations to improve code readability and maintainability. For example: std::vector<int>::iterator I = my_container.begin(); // transforms to: auto I = my_container.begin(); The auto type specifier will only be introduced in situations where the variable type matches the type of the initializer expression. In other words auto should deduce the same type that was originally spelled in the source. However, not every situation should be transformed: int val = 42; InfoStruct &I = SomeObject.getInfo(); // Should not become: auto val = 42; auto &I = SomeObject.getInfo(); In this example using auto for builtins doesn't improve readability. In other situations it makes the code less self-documenting impairing readability and maintainability. As a result, auto is used only intro- duced in specific situations described below. Iterators Iterator type specifiers tend to be long and used frequently, espe- cially in loop constructs. Since the functions generating iterators have a common format, the type specifier can be replaced without ob- scuring the meaning of code while improving readability and maintain- ability. for (std::vector<int>::iterator I = my_container.begin(), E = my_container.end(); I != E; ++I) { } // becomes for (auto I = my_container.begin(), E = my_container.end(); I != E; ++I) { } The check will only replace iterator type-specifiers when all of the following conditions are satisfied: • The iterator is for one of the standard containers in std namespace: • array • deque • forward_list • list • vector • map • multimap • set • multiset • unordered_map • unordered_multimap • unordered_set • unordered_multiset • queue • priority_queue • stack • The iterator is one of the possible iterator types for standard con- tainers: • iterator • reverse_iterator • const_iterator • const_reverse_iterator • In addition to using iterator types directly, typedefs or other ways of referring to those types are also allowed. However, implementa- tion-specific types for which a type like std::vector<int>::iterator is itself a typedef will not be transformed. Consider the following examples: // The following direct uses of iterator types will be transformed. std::vector<int>::iterator I = MyVec.begin(); { using namespace std; list<int>::iterator I = MyList.begin(); } // The type specifier for J would transform to auto since it's a typedef // to a standard iterator type. typedef std::map<int, std::string>::const_iterator map_iterator; map_iterator J = MyMap.begin(); // The following implementation-specific iterator type for which // std::vector<int>::iterator could be a typedef would not be transformed. __gnu_cxx::__normal_iterator<int*, std::vector> K = MyVec.begin(); • The initializer for the variable being declared is not a braced ini- tializer list. Otherwise, use of auto would cause the type of the variable to be deduced as std::initializer_list. New expressions Frequently, when a pointer is declared and initialized with new, the pointee type is written twice: in the declaration type and in the new expression. In this case, the declaration type can be replaced with auto improving readability and maintainability. TypeName *my_pointer = new TypeName(my_param); // becomes auto *my_pointer = new TypeName(my_param); The check will also replace the declaration type in multiple declara- tions, if the following conditions are satisfied: • All declared variables have the same type (i.e. all of them are pointers to the same type). • All declared variables are initialized with a new expression. • The types of all the new expressions are the same than the pointee of the declaration type. TypeName *my_first_pointer = new TypeName, *my_second_pointer = new TypeName; // becomes auto *my_first_pointer = new TypeName, *my_second_pointer = new TypeName; Cast expressions Frequently, when a variable is declared and initialized with a cast, the variable type is written twice: in the declaration type and in the cast expression. In this case, the declaration type can be replaced with auto improving readability and maintainability. TypeName *my_pointer = static_cast<TypeName>(my_param); // becomes auto *my_pointer = static_cast<TypeName>(my_param); The check handles static_cast, dynamic_cast, const_cast, reinter- pret_cast, functional casts, C-style casts and function templates that behave as casts, such as llvm::dyn_cast, boost::lexical_cast and gsl::narrow_cast. Calls to function templates are considered to behave as casts if the first template argument is explicit and is a type, and the function returns that type, or a pointer or reference to it. Known Limitations • If the initializer is an explicit conversion constructor, the check will not replace the type specifier even though it would be safe to do so. • User-defined iterators are not handled at this time. Options MinTypeNameLength If the option is set to non-zero (default 5), the check will ig- nore type names having a length less than the option value. The option affects expressions only, not iterators. Spaces between multi-lexeme type names (long int) are considered as one. If the RemoveStars option (see below) is set to true, then *s in the type are also counted as a part of the type name. // MinTypeNameLength = 0, RemoveStars=0 int a = static_cast<int>(foo()); // ---> auto a = ... // length(bool *) = 4 bool *b = new bool; // ---> auto *b = ... unsigned c = static_cast<unsigned>(foo()); // ---> auto c = ... // MinTypeNameLength = 5, RemoveStars=0 int a = static_cast<int>(foo()); // ---> int a = ... bool b = static_cast<bool>(foo()); // ---> bool b = ... bool *pb = static_cast<bool*>(foo()); // ---> bool *pb = ... unsigned c = static_cast<unsigned>(foo()); // ---> auto c = ... // length(long <on-or-more-spaces> int) = 8 long int d = static_cast<long int>(foo()); // ---> auto d = ... // MinTypeNameLength = 5, RemoveStars=1 int a = static_cast<int>(foo()); // ---> int a = ... // length(int * * ) = 5 int **pa = static_cast<int**>(foo()); // ---> auto pa = ... bool b = static_cast<bool>(foo()); // ---> bool b = ... bool *pb = static_cast<bool*>(foo()); // ---> auto pb = ... unsigned c = static_cast<unsigned>(foo()); // ---> auto c = ... long int d = static_cast<long int>(foo()); // ---> auto d = ... RemoveStars If the option is set to true (default is false), the check will remove stars from the non-typedef pointer types when replacing type names with auto. Otherwise, the check will leave stars. For example: TypeName *my_first_pointer = new TypeName, *my_second_pointer = new TypeName; // RemoveStars = 0 auto *my_first_pointer = new TypeName, *my_second_pointer = new TypeName; // RemoveStars = 1 auto my_first_pointer = new TypeName, my_second_pointer = new TypeName; modernize-use-bool-literals Finds integer literals which are cast to bool. bool p = 1; bool f = static_cast<bool>(1); std::ios_base::sync_with_stdio(0); bool x = p ? 1 : 0; // transforms to bool p = true; bool f = true; std::ios_base::sync_with_stdio(false); bool x = p ? true : false; Options IgnoreMacros If set to true, the check will not give warnings inside macros. Default is true. modernize-use-constraints Replace std::enable_if with C++20 requires clauses. std::enable_if is a SFINAE mechanism for selecting the desired function or class template based on type traits or other requirements. enable_if changes the meta-arity of the template, and has other adverse side ef- fects in the code. C++20 introduces concepts and constraints as a cleaner language provided solution to achieve the same outcome. This check finds some common std::enable_if patterns that can be re- placed by C++20 requires clauses. The tool can replace some of these patterns automatically, otherwise, the tool will emit a diagnostic without a replacement. The tool can detect the following std::enable_if patterns 1. std::enable_if in the return type of a function 2. std::enable_if as the trailing template parameter for function tem- plates Other uses, for example, in class templates for function parameters, are not currently supported by this tool. Other variants such as boost::enable_if are not currently supported by this tool. Below are some examples of code using std::enable_if. // enable_if in function return type template <typename T> std::enable_if_t<T::some_trait, int> only_if_t_has_the_trait() { ... } // enable_if in the trailing template parameter template <typename T, std::enable_if_t<T::some_trait, int> = 0> void another_version() { ... } template <typename T> typename std::enable_if<T::some_value, Obj>::type existing_constraint() requires (T::another_value) { return Obj{}; } template <typename T, std::enable_if_t<T::some_trait, int> = 0> struct my_class {}; The tool will replace the above code with, // warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints] template <typename T> int only_if_t_has_the_trait() requires T::some_trait { ... } // warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints] template <typename T> void another_version() requires T::some_trait { ... } // The tool will emit a diagnostic for the following, but will // not attempt to replace the code. // warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints] template <typename T> typename std::enable_if<T::some_value, Obj>::type existing_constraint() requires (T::another_value) { return Obj{}; } // The tool will not emit a diagnostic or attempt to replace the code. template <typename T, std::enable_if_t<T::some_trait, int> = 0> struct my_class {}; modernize-use-default This check has been renamed to modernize-use-equals-default. modernize-use-default-member-init This check converts constructors' member initializers into the new de- fault member initializers in C++11. Other member initializers that match the default member initializer are removed. This can reduce re- peated code or allow use of '= default'. struct A { A() : i(5), j(10.0) {} A(int i) : i(i), j(10.0) {} int i; double j; }; // becomes struct A { A() {} A(int i) : i(i) {} int i{5}; double j{10.0}; }; NOTE: Only converts member initializers for built-in types, enums, and pointers. The readability-redundant-member-init check will remove redundant member initializers for classes. Options UseAssignment If this option is set to true (default is false), the check will initialize members with an assignment. For example: struct A { A() {} A(int i) : i(i) {} int i = 5; double j = 10.0; }; IgnoreMacros If this option is set to true (default is true), the check will not warn about members declared inside macros. modernize-use-emplace The check flags insertions to an STL-style container done by calling the push_back, push, or push_front methods with an explicitly-con- structed temporary of the container element type. In this case, the corresponding emplace equivalent methods result in less verbose and po- tentially more efficient code. Right now the check doesn't support in- sert. It also doesn't support insert functions for associative contain- ers because replacing insert with emplace may result in speed regres- sion, but it might get support with some addition flag in the future. The ContainersWithPushBack, ContainersWithPush, and ContainersWithPushFront options are used to specify the container types that support the push_back, push, and push_front operations respec- tively. The default values for these options are as follows: • ContainersWithPushBack: std::vector, std::deque, and std::list. • ContainersWithPush: std::stack, std::queue, and std::priority_queue. • ContainersWithPushFront: std::forward_list, std::list, and std::deque. This check also reports when an emplace-like method is improperly used, for example using emplace_back while also calling a constructor. This creates a temporary that requires at best a move and at worst a copy. Almost all emplace-like functions in the STL are covered by this, with try_emplace on std::map and std::unordered_map being the exception as it behaves slightly differently than all the others. More containers can be added with the EmplacyFunctions option, so long as the container defines a value_type type, and the emplace-like functions construct a value_type object. Before: std::vector<MyClass> v; v.push_back(MyClass(21, 37)); v.emplace_back(MyClass(21, 37)); std::vector<std::pair<int, int>> w; w.push_back(std::pair<int, int>(21, 37)); w.push_back(std::make_pair(21L, 37L)); w.emplace_back(std::make_pair(21L, 37L)); After: std::vector<MyClass> v; v.emplace_back(21, 37); v.emplace_back(21, 37); std::vector<std::pair<int, int>> w; w.emplace_back(21, 37); w.emplace_back(21L, 37L); w.emplace_back(21L, 37L); By default, the check is able to remove unnecessary std::make_pair and std::make_tuple calls from push_back calls on containers of std::pair and std::tuple. Custom tuple-like types can be modified by the TupleTypes option; custom make functions can be modified by the TupleMakeFunctions option. The other situation is when we pass arguments that will be converted to a type inside a container. Before: std::vector<boost::optional<std::string> > v; v.push_back("abc"); After: std::vector<boost::optional<std::string> > v; v.emplace_back("abc"); In some cases the transformation would be valid, but the code wouldn't be exception safe. In this case the calls of push_back won't be re- placed. std::vector<std::unique_ptr<int>> v; v.push_back(std::unique_ptr<int>(new int(0))); auto *ptr = new int(1); v.push_back(std::unique_ptr<int>(ptr)); This is because replacing it with emplace_back could cause a leak of this pointer if emplace_back would throw exception before emplacement (e.g. not enough memory to add a new element). For more info read item 42 - "Consider emplacement instead of inser- tion." of Scott Meyers "Effective Modern C++". The default smart pointers that are considered are std::unique_ptr, std::shared_ptr, std::auto_ptr. To specify other smart pointers or other classes use the SmartPointers option. Check also doesn't fire if any argument of the constructor call would be: • a bit-field (bit-fields can't bind to rvalue/universal reference) • a new expression (to avoid leak) • if the argument would be converted via derived-to-base cast. This check requires C++11 or higher to run. Options ContainersWithPushBack Semicolon-separated list of class names of custom containers that support push_back. ContainersWithPush Semicolon-separated list of class names of custom containers that support push. ContainersWithPushFront Semicolon-separated list of class names of custom containers that support push_front. IgnoreImplicitConstructors When true, the check will ignore implicitly constructed argu- ments of push_back, e.g. std::vector<std::string> v; v.push_back("a"); // Ignored when IgnoreImplicitConstructors is `true`. Default is false. SmartPointers Semicolon-separated list of class names of custom smart point- ers. TupleTypes Semicolon-separated list of std::tuple-like class names. TupleMakeFunctions Semicolon-separated list of std::make_tuple-like function names. Those function calls will be removed from push_back calls and turned into emplace_back. EmplacyFunctions Semicolon-separated list of containers without their template parameters and some emplace-like method of the container. Exam- ple: vector::emplace_back. Those methods will be checked for im- proper use and the check will report when a temporary is unnec- essarily created. Example std::vector<MyTuple<int, bool, char>> x; x.push_back(MakeMyTuple(1, false, 'x')); x.emplace_back(MakeMyTuple(1, false, 'x')); transforms to: std::vector<MyTuple<int, bool, char>> x; x.emplace_back(1, false, 'x'); x.emplace_back(1, false, 'x'); when TupleTypes is set to MyTuple, TupleMakeFunctions is set to MakeMy- Tuple, and EmplacyFunctions is set to vector::emplace_back. modernize-use-equals-default This check replaces default bodies of special member functions with = default;. The explicitly defaulted function declarations enable more opportunities in optimization, because the compiler might treat explic- itly defaulted functions as trivial. struct A { A() {} ~A(); }; A::~A() {} // becomes struct A { A() = default; ~A(); }; A::~A() = default; NOTE: Move-constructor and move-assignment operator are not supported yet. Options IgnoreMacros If set to true, the check will not give warnings inside macros and will ignore special members with bodies contain macros or preprocessor directives. Default is true. modernize-use-equals-delete Identifies unimplemented private special member functions, and recom- mends using = delete for them. Additionally, it recommends relocating any deleted member function from the private to the public section. Before the introduction of C++11, the primary method to effectively "erase" a particular function involved declaring it as private without providing a definition. This approach would result in either a compiler error (when attempting to call a private function) or a linker error (due to an undefined reference). However, subsequent to the advent of C++11, a more conventional ap- proach emerged for achieving this purpose. It involves flagging func- tions as = delete and keeping them in the public section of the class. To prevent false positives, this check is only active within a transla- tion unit where all other member functions have been implemented. The check will generate partial fixes by introducing = delete, but the user is responsible for manually relocating functions to the public section. // Example: bad class A { private: A(const A&); A& operator=(const A&); }; // Example: good class A { public: A(const A&) = delete; A& operator=(const A&) = delete; }; IgnoreMacros If this option is set to true (default is true), the check will not warn about functions declared inside macros. modernize-use-nodiscard Adds [[nodiscard]] attributes (introduced in C++17) to member functions in order to highlight at compile time which return values should not be ignored. Member functions need to satisfy the following conditions to be consid- ered by this check: • no [[nodiscard]], [[noreturn]], __attribute__((warn_unused_re- sult)), [[clang::warn_unused_result]] nor [[gcc::warn_unused_re- sult]] attribute, • non-void return type, • non-template return types, • const member function, • non-variadic functions, • no non-const reference parameters, • no pointer parameters, • no template parameters, • no template function parameters, • not be a member of a class with mutable member variables, • no Lambdas, • no conversion functions. Such functions have no means of altering any state or passing values other than via the return type. Unless the member functions are alter- ing state via some external call (e.g. I/O). Example bool empty() const; bool empty(int i) const; transforms to: [[nodiscard]] bool empty() const; [[nodiscard]] bool empty(int i) const; Options ReplacementString Specifies a macro to use instead of [[nodiscard]]. This is use- ful when maintaining source code that needs to compile with a pre-C++17 compiler. Example bool empty() const; bool empty(int i) const; transforms to: NO_DISCARD bool empty() const; NO_DISCARD bool empty(int i) const; if the ReplacementString option is set to NO_DISCARD. NOTE: If the ReplacementString is not a C++ attribute, but instead a macro, then that macro must be defined in scope or the fix-it will not be applied. NOTE: For alternative __attribute__ syntax options to mark functions as [[nodiscard]] in non-c++17 source code. See https://clang.llvm.org/docs/AttributeReference.html#nodiscard-warn-unused-result modernize-use-noexcept This check replaces deprecated dynamic exception specifications with the appropriate noexcept specification (introduced in C++11). By de- fault this check will replace throw() with noexcept, and throw(<excep- tion>[,...]) or throw(...) with noexcept(false). Example void foo() throw(); void bar() throw(int) {} transforms to: void foo() noexcept; void bar() noexcept(false) {} Options ReplacementString Users can use ReplacementString to specify a macro to use in- stead of noexcept. This is useful when maintaining source code that uses custom exception specification marking other than noexcept. Fix-it hints will only be generated for non-throwing specifications. Example void bar() throw(int); void foo() throw(); transforms to: void bar() throw(int); // No fix-it generated. void foo() NOEXCEPT; if the ReplacementString option is set to NOEXCEPT. UseNoexceptFalse Enabled by default, disabling will generate fix-it hints that remove throwing dynamic exception specs, e.g., throw(<something>), completely without providing a replacement text, except for destructors and delete operators that are noexcept(true) by default. Example void foo() throw(int) {} struct bar { void foobar() throw(int); void operator delete(void *ptr) throw(int); void operator delete[](void *ptr) throw(int); ~bar() throw(int); } transforms to: void foo() {} struct bar { void foobar(); void operator delete(void *ptr) noexcept(false); void operator delete[](void *ptr) noexcept(false); ~bar() noexcept(false); } if the UseNoexceptFalse option is set to false. modernize-use-nullptr The check converts the usage of null pointer constants (e.g. NULL, 0) to use the new C++11 nullptr keyword. Example void assignment() { char *a = NULL; char *b = 0; char c = 0; } int *ret_ptr() { return 0; } transforms to: void assignment() { char *a = nullptr; char *b = nullptr; char c = 0; } int *ret_ptr() { return nullptr; } Options IgnoredTypes Semicolon-separated list of regular expressions to match pointer types for which implicit casts will be ignored. Default value: std::_CmpUnspecifiedParam::;^std::__cmp_cat::__unspec. NullMacros Comma-separated list of macro names that will be transformed along with NULL. By default this check will only replace the NULL macro and will skip any similar user-defined macros. Example #define MY_NULL (void*)0 void assignment() { void *p = MY_NULL; } transforms to: #define MY_NULL NULL void assignment() { int *p = nullptr; } if the NullMacros option is set to MY_NULL. modernize-use-override Adds override (introduced in C++11) to overridden virtual functions and removes virtual from those functions as it is not required. virtual on non base class implementations was used to help indicate to the user that a function was virtual. C++ compilers did not use the presence of this to signify an overridden function. In C++ 11 override and final keywords were introduced to allow overrid- den functions to be marked appropriately. Their presence allows compil- ers to verify that an overridden function correctly overrides a base class implementation. This can be useful as compilers can generate a compile time error when: • The base class implementation function signature changes. • The user has not created the override with the correct signature. Options IgnoreDestructors If set to true, this check will not diagnose destructors. De- fault is false. IgnoreTemplateInstantiations If set to true, instructs this check to ignore virtual function overrides that are part of template instantiations. Default is false. AllowOverrideAndFinal If set to true, this check will not diagnose override as redun- dant with final. This is useful when code will be compiled by a compiler with warning/error checking flags requiring override explicitly on overridden members, such as gcc -Wsuggest-over- ride/gcc -Werror=suggest-override. Default is false. OverrideSpelling Specifies a macro to use instead of override. This is useful when maintaining source code that also needs to compile with a pre-C++11 compiler. FinalSpelling Specifies a macro to use instead of final. This is useful when maintaining source code that also needs to compile with a pre-C++11 compiler. NOTE: For more information on the use of override see https://en.cppreference.com/w/cpp/language/override modernize-use-starts-ends-with Checks whether a find or rfind result is compared with 0 and suggests replacing with starts_with when the method exists in the class. No- tably, this will work with std::string and std::string_view. std::string s = "..."; if (s.find("prefix") == 0) { /* do something */ } if (s.rfind("prefix", 0) == 0) { /* do something */ } becomes std::string s = "..."; if (s.starts_with("prefix")) { /* do something */ } if (s.starts_with("prefix")) { /* do something */ } modernize-use-std-numbers Finds constants and function calls to math functions that can be re- placed with C++20's mathematical constants from the numbers header and offers fix-it hints. Does not match the use of variables with that value, and instead, offers a replacement for the definition of those variables. Function calls that match the pattern of how the constant is calculated are matched and replaced with the std::numbers constant. The use of macros gets replaced with the corresponding std::numbers constant, instead of changing the macro definition. The following list of constants from the numbers header are supported: • e • log2e • log10e • pi • inv_pi • inv_sqrtpi • ln2 • ln10 • sqrt2 • sqrt3 • inv_sqrt3 • egamma • phi The list currently includes all constants as of C++20. The replacements use the type of the matched constant and can remove explicit casts, i.e., switching between std::numbers::e, std::num- bers::e_v<float> and std::numbers::e_v<long double> where appropriate. double sqrt(double); double log2(double); void sink(auto&&) {} void floatSink(float); #define MY_PI 3.1415926 void foo() { const double Pi = 3.141592653589; // const double Pi = std::numbers::pi const auto Use = Pi / 2; // no match for Pi static constexpr double Euler = 2.7182818; // static constexpr double Euler = std::numbers::e; log2(exp(1)); // std::numbers::log2e; log2(Euler); // std::numbers::log2e; 1 / sqrt(MY_PI); // std::numbers::inv_sqrtpi; sink(MY_PI); // sink(std::numbers::pi); floatSink(MY_PI); // floatSink(std::numbers::pi); floatSink(static_cast<float>(MY_PI)); // floatSink(std::numbers::pi_v<float>); } Options DiffThreshold A floating point value that sets the detection threshold for when literals match a constant. A literal matches a constant if abs(literal - constant) < DiffThreshold evaluates to true. De- fault is 0.001. IncludeStyle A string specifying which include-style is used, llvm or google. Default is llvm. modernize-use-std-print Converts calls to printf, fprintf, absl::PrintF and absl::FPrintf to equivalent calls to C++23's std::print or std::println as appropriate, modifying the format string appropriately. The replaced and replace- ment functions can be customised by configuration options. Each argu- ment that is the result of a call to std::string::c_str() and std::string::data() will have that now-unnecessary call removed in a similar manner to the readability-redundant-string-cstr check. In other words, it turns lines like: fprintf(stderr, "The %s is %3d\n", description.c_str(), value); into: std::println(stderr, "The {} is {:3}", description, value); If the ReplacementPrintFunction or ReplacementPrintlnFunction options are left, or assigned to their default values then this check is only enabled with -std=c++23 or later. The check doesn't do a bad job, but it's not perfect. In particular: • It assumes that the format string is correct for the arguments. If you get any warnings when compiling with -Wformat then misbehaviour is possible. • At the point that the check runs, the AST contains a single StringLiteral for the format string and any macro expansion, token pasting, adjacent string literal concatenation and escaping has been handled. Although it's possible for the check to automatically put the escapes back, they may not be exactly as they were written (e.g. "\x0a" will become "\n" and "ab" "cd" will become "abcd".) This is helpful since it means that the PRIx macros from <inttypes.h> are re- moved correctly. • It supports field widths, precision, positional arguments, leading zeros, leading +, alignment and alternative forms. • Use of any unsupported flags or specifiers will cause the entire statement to be left alone and a warning to be emitted. Particular unsupported features are: • The %' flag for thousands separators. • The glibc extension %m. • printf and similar functions return the number of characters printed. std::print does not. This means that any invocations that use the re- turn value will not be converted. Unfortunately this currently in- cludes explicitly-casting to void. Deficiencies in this check mean that any invocations inside GCC compound statements cannot be con- verted even if the resulting value is not used. If conversion would be incomplete or unsafe then the entire invocation will be left unchanged. If the call is deemed suitable for conversion then: • printf, fprintf, absl::PrintF, absl::FPrintF and any functions speci- fied by the PrintfLikeFunctions option or FprintfLikeFunctions are replaced with the function specified by the ReplacementPrintlnFunc- tion option if the format string ends with \n or ReplacementPrint- Function otherwise. • the format string is rewritten to use the std::formatter language. If a \n is found at the end of the format string not preceded by r then it is removed and ReplacementPrintlnFunction is used rather than Re- placementPrintFunction. • any arguments that corresponded to %p specifiers that std::formatter wouldn't accept are wrapped in a static_cast to const void *. • any arguments that corresponded to %s specifiers where the argument is of signed char or unsigned char type are wrapped in a reinter- pret_cast<const char *>. • any arguments where the format string and the parameter differ in signedness will be wrapped in an appropriate static_cast if Strict- Mode is enabled. • any arguments that end in a call to std::string::c_str() or std::string::data() will have that call removed. Options StrictMode When true, the check will add casts when converting from variadic functions like printf and printing signed or un- signed integer types (including fixed-width integer types from <cstdint>, ptrdiff_t, size_t and ssize_t) as the oppo- site signedness to ensure that the output matches that of printf. This does not apply when converting from non-variadic functions such as absl::PrintF and fmt::printf. For example, with StrictMode enabled: int i = -42; unsigned int u = 0xffffffff; printf("%d %u\n", i, u); would be converted to: std::print("{} {}\n", static_cast<unsigned int>(i), static_cast<int>(u)); to ensure that the output will continue to be the unsigned rep- resentation of -42 and the signed representation of 0xffffffff (often 4294967254 and -1 respectively.) When false (which is the default), these casts will not be added which may cause a change in the output. PrintfLikeFunctions A semicolon-separated list of (fully qualified) extra function names to replace, with the requirement that the first parameter contains the printf-style format string and the arguments to be formatted follow immediately afterwards. If neither this option nor FprintfLikeFunctions are set then the default value for this option is printf; absl::PrintF, otherwise it is empty. FprintfLikeFunctions A semicolon-separated list of (fully qualified) extra function names to replace, with the requirement that the first parameter is retained, the second parameter contains the printf-style for- mat string and the arguments to be formatted follow immediately afterwards. If neither this option nor PrintfLikeFunctions are set then the default value for this option is fprintf; absl::FPrintF, otherwise it is empty. ReplacementPrintFunction The function that will be used to replace printf, fprintf etc. during conversion rather than the default std::print when the originalformat string does not end with \n. It is expected that the function provides an interface that is compatible with std::print. A suitable candidate would be fmt::print. ReplacementPrintlnFunction The function that will be used to replace printf, fprintf etc. during conversion rather than the default std::println when the original format string ends with \n. It is expected that the function provides an interface that is compatible with std::println. A suitable candidate would be fmt::println. PrintHeader The header that must be included for the declaration of Replace- mentPrintFunction so that a #include directive can be added if required. If ReplacementPrintFunction is std::print then this option will default to <print>, otherwise this option will de- fault to nothing and no #include directive will be added. modernize-use-trailing-return-type Rewrites function signatures to use a trailing return type (introduced in C++11). This transformation is purely stylistic. The return type before the function name is replaced by auto and inserted after the function parameter list (and qualifiers). Example int f1(); inline int f2(int arg) noexcept; virtual float f3() const && = delete; transforms to: auto f1() -> int; inline auto f2(int arg) -> int noexcept; virtual auto f3() const && -> float = delete; Known Limitations The following categories of return types cannot be rewritten currently: • function pointers • member function pointers • member pointers Unqualified names in the return type might erroneously refer to differ- ent entities after the rewrite. Preventing such errors requires a full lookup of all unqualified names present in the return type in the scope of the trailing return type location. This location includes e.g. function parameter names and members of the enclosing class (including all inherited classes). Such a lookup is currently not implemented. Given the following piece of code struct S { long long value; }; S f(unsigned S) { return {S * 2}; } class CC { int S; struct S m(); }; S CC::m() { return {0}; } a careless rewrite would produce the following output: struct S { long long value; }; auto f(unsigned S) -> S { return {S * 2}; } // error class CC { int S; auto m() -> struct S; }; auto CC::m() -> S { return {0}; } // error This code fails to compile because the S in the context of f refers to the equally named function parameter. Similarly, the S in the context of m refers to the equally named class member. The check can currently only detect and avoid a clash with a function parameter name. modernize-use-transparent-functors Prefer transparent functors to non-transparent ones. When using trans- parent functors, the type does not need to be repeated. The code is easier to read, maintain and less prone to errors. It is not possible to introduce unwanted conversions. // Non-transparent functor std::map<int, std::string, std::greater<int>> s; // Transparent functor. std::map<int, std::string, std::greater<>> s; // Non-transparent functor using MyFunctor = std::less<MyType>; It is not always a safe transformation though. The following case will be untouched to preserve the semantics. // Non-transparent functor std::map<const char *, std::string, std::greater<std::string>> s; Options SafeMode If the option is set to true, the check will not diagnose cases where using a transparent functor cannot be guaranteed to pro- duce identical results as the original code. The default value for this option is false. This check requires using C++14 or higher to run. modernize-use-uncaught-exceptions This check will warn on calls to std::uncaught_exception and replace them with calls to std::uncaught_exceptions, since std::uncaught_excep- tion was deprecated in C++17. Below are a few examples of what kind of occurrences will be found and what they will be replaced with. #define MACRO1 std::uncaught_exception #define MACRO2 std::uncaught_exception int uncaught_exception() { return 0; } int main() { int res; res = uncaught_exception(); // No warning, since it is not the deprecated function from namespace std res = MACRO2(); // Warning, but will not be replaced res = std::uncaught_exception(); // Warning and replaced using std::uncaught_exception; // Warning and replaced res = uncaught_exception(); // Warning and replaced } After applying the fixes the code will look like the following: #define MACRO1 std::uncaught_exception #define MACRO2 std::uncaught_exception int uncaught_exception() { return 0; } int main() { int res; res = uncaught_exception(); res = MACRO2(); res = std::uncaught_exceptions(); using std::uncaught_exceptions; res = uncaught_exceptions(); } modernize-use-using The check converts the usage of typedef with using keyword. Before: typedef int variable; class Class{}; typedef void (Class::* MyPtrType)() const; typedef struct { int a; } R_t, *R_p; After: using variable = int; class Class{}; using MyPtrType = void (Class::*)() const; using R_t = struct { int a; }; using R_p = R_t*; The checker ignores typedef within extern "C" { ... } blocks. extern "C" { typedef int InExternC; // Left intact. } This check requires using C++11 or higher to run. Options IgnoreMacros If set to true, the check will not give warnings inside macros. Default is true. IgnoreExternC If set to true, the check will not give warning inside extern "C"`scope. Default is `false mpi-buffer-deref This check verifies if a buffer passed to an MPI (Message Passing In- terface) function is sufficiently dereferenced. Buffers should be passed as a single pointer or array. As MPI function signatures specify void * for their buffer types, insufficiently dereferenced buffers can be passed, like for example as double pointers or multidimensional ar- rays, without a compiler warning emitted. Examples: // A double pointer is passed to the MPI function. char *buf; MPI_Send(&buf, 1, MPI_CHAR, 0, 0, MPI_COMM_WORLD); // A multidimensional array is passed to the MPI function. short buf[1][1]; MPI_Send(buf, 1, MPI_SHORT, 0, 0, MPI_COMM_WORLD); // A pointer to an array is passed to the MPI function. short *buf[1]; MPI_Send(buf, 1, MPI_SHORT, 0, 0, MPI_COMM_WORLD); mpi-type-mismatch This check verifies if buffer type and MPI (Message Passing Interface) datatype pairs match for used MPI functions. All MPI datatypes defined by the MPI standard (3.1) are verified by this check. User defined typedefs, custom MPI datatypes and null pointer constants are skipped, in the course of verification. Example: // In this case, the buffer type matches MPI datatype. char buf; MPI_Send(&buf, 1, MPI_CHAR, 0, 0, MPI_COMM_WORLD); // In the following case, the buffer type does not match MPI datatype. int buf; MPI_Send(&buf, 1, MPI_CHAR, 0, 0, MPI_COMM_WORLD); objc-assert-equals Finds improper usages of XCTAssertEqual and XCTAssertNotEqual and re- places them with XCTAssertEqualObjects or XCTAssertNotEqualObjects. This makes tests less fragile, as many improperly rely on pointer equality for strings that have equal values. This assumption is not guaranteed by the language. objc-avoid-nserror-init Finds improper initialization of NSError objects. According to Apple developer document, we should always use factory method errorWithDomain:code:userInfo: to create new NSError objects in- stead of [NSError alloc] init]. Otherwise it will lead to a warning message during runtime. The corresponding information about NSError creation: https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/ErrorHandlingCocoa/CreateCustomizeNSError/CreateCustomizeNSError.html objc-dealloc-in-category Finds implementations of -dealloc in Objective-C categories. The cate- gory implementation will override any -dealloc in the class implementa- tion, potentially causing issues. Classes implement -dealloc to perform important actions to deallocate an object. If a category on the class implements -dealloc, it will override the class's implementation and unexpected deallocation behav- ior may occur. objc-forbidden-subclassing Finds Objective-C classes which are subclasses of classes which are not designed to be subclassed. By default, includes a list of Objective-C classes which are publicly documented as not supporting subclassing. NOTE: Instead of using this check, for code under your control, you should add __attribute__((objc_subclassing_restricted)) before your @inter- face declarations to ensure the compiler prevents others from sub- classing your Objective-C classes. See https://clang.llvm.org/docs/AttributeReference.html#objc-subclassing-restricted Options ForbiddenSuperClassNames Semicolon-separated list of names of Objective-C classes which do not support subclassing. Defaults to ABNewPersonViewController;ABPeoplePickerNavigation- Controller;ABPersonViewController;ABUnknownPersonViewCon- troller;NSHashTable;NSMapTable;NSPointerArray;NSPointerFunc- tions;NSTimer;UIActionSheet;UIAlertView;UIImagePickerCon- troller;UITextInputMode;UIWebView. objc-missing-hash Finds Objective-C implementations that implement -isEqual: without also appropriately implementing -hash. Apple documentation highlights that objects that are equal must have the same hash value: https://developer.apple.com/documentation/objectivec/1418956-nsobject/1418795-isequal?language=objc Note that the check only verifies the presence of -hash in scenarios where its omission could result in unexpected behavior. The verifica- tion of the implementation of -hash is the responsibility of the devel- oper, e.g., through the addition of unit tests to verify the implemen- tation. objc-nsdate-formatter When NSDateFormatter is used to convert an NSDate type to a String type, the user can specify a custom format string. Certain format spec- ifiers are undesirable despite being legal. See http://www.unicode.org/reports/tr35/tr35-dates.html#Date_Format_Patterns for all legal date patterns. This checker reports as warnings the following string patterns in a date format specifier: 1. yyyy + ww : Calendar year specified with week of a week year (unless YYYY is also specified). • Example 1: Input Date: 29 December 2014 ; Format String: yyyy-ww; Output string: 2014-01 (Wrong because its not the first week of 2014) • Example 2: Input Date: 29 December 2014 ; Format String: dd-MM-yyyy (ww-YYYY); Output string: 29-12-2014 (01-2015) (This is correct) 2. F without ee/EE : Numeric day of week in a month without actual day. • Example: Input Date: 29 December 2014 ; Format String: F-MM; Output string: 5-12 (Wrong because it reads as 5th ___ of Dec in English) 3. F without MM : Numeric day of week in a month without month. • Example: Input Date: 29 December 2014 ; Format String: F-EE Output string: 5-Mon (Wrong because it reads as 5th Mon of ___ in English) 4. WW without MM : Week of the month without the month. • Example: Input Date: 29 December 2014 ; Format String: WW-yyyy Output string: 05-2014 (Wrong because it reads as 5th Week of ___ in English) 5. YYYY + QQ : Week year specified with quarter of normal year (unless yyyy is also specified). • Example 1: Input Date: 29 December 2014 ; Format String: YYYY-QQ Output string: 2015-04 (Wrong because its not the 4th quarter of 2015) • Example 2: Input Date: 29 December 2014 ; Format String: ww-YYYY (QQ-yyyy) Output string: 01-2015 (04-2014) (This is correct) 6. YYYY + MM : Week year specified with Month of a calendar year (un- less yyyy is also specified). • Example 1: Input Date: 29 December 2014 ; Format String: YYYY-MM Output string: 2015-12 (Wrong because its not the 12th month of 2015) • Example 2: Input Date: 29 December 2014 ; Format String: ww-YYYY (MM-yyyy) Output string: 01-2015 (12-2014) (This is correct) 7. YYYY + DD : Week year with day of a calendar year (unless yyyy is also specified). • Example 1: Input Date: 29 December 2014 ; Format String: YYYY-DD Output string: 2015-363 (Wrong because its not the 363rd day of 2015) • Example 2: Input Date: 29 December 2014 ; Format String: ww-YYYY (DD-yyyy) Output string: 01-2015 (363-2014) (This is correct) 8. YYYY + WW : Week year with week of a calendar year (unless yyyy is also specified). • Example 1: Input Date: 29 December 2014 ; Format String: YYYY-WW Output string: 2015-05 (Wrong because its not the 5th week of 2015) • Example 2: Input Date: 29 December 2014 ; Format String: ww-YYYY (WW-MM-yyyy) Output string: 01-2015 (05-12-2014) (This is correct) 9. YYYY + F : Week year with day of week in a calendar month (unless yyyy is also specified). • Example 1: Input Date: 29 December 2014 ; Format String: YYYY-ww-F-EE Output string: 2015-01-5-Mon (Wrong because its not the 5th Monday of January in 2015) • Example 2: Input Date: 29 December 2014 ; Format String: ww-YYYY (F-EE-MM-yyyy) Output string: 01-2015 (5-Mon-12-2014) (This is correct) objc-nsinvocation-argument-lifetime Finds calls to NSInvocation methods under ARC that don't have proper argument object lifetimes. When passing Objective-C objects as parame- ters to the NSInvocation methods getArgument:atIndex: and getReturn- Value:, the values are copied by value into the argument pointer, which leads to incorrect releasing behavior if the object pointers are not declared __unsafe_unretained. For code: id arg; [invocation getArgument:&arg atIndex:2]; __strong id returnValue; [invocation getReturnValue:&returnValue]; The fix will be: __unsafe_unretained id arg; [invocation getArgument:&arg atIndex:2]; __unsafe_unretained id returnValue; [invocation getReturnValue:&returnValue]; The check will warn on being passed instance variable references that have lifetimes other than __unsafe_unretained, but does not propose a fix: // "id _returnValue" is declaration of instance variable of class. [invocation getReturnValue:&self->_returnValue]; objc-property-declaration Finds property declarations in Objective-C files that do not follow the pattern of property names in Apple's programming guide. The property name should be in the format of Lower Camel Case. For code: @property(nonatomic, assign) int LowerCamelCase; The fix will be: @property(nonatomic, assign) int lowerCamelCase; The check will only fix 'CamelCase' to 'camelCase'. In some other cases we will only provide warning messages since the property name could be complicated. Users will need to come up with a proper name by their own. This check also accepts special acronyms as prefixes or suffixes. Such prefixes or suffixes will suppress the Lower Camel Case check according to the guide: https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/CodingGuidelines/Articles/NamingBasics.html#//apple_ref/doc/uid/20001281-1002931-BBCFHEAB For a full list of well-known acronyms: https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/CodingGuidelines/Articles/APIAbbreviations.html#//apple_ref/doc/uid/20001285-BCIHCGAE The corresponding style rule: https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/CodingGuidelines/Articles/NamingIvarsAndTypes.html#//apple_ref/doc/uid/20001284-1001757 The check will also accept property declared in category with a prefix of lowercase letters followed by a '_' to avoid naming conflict. For example: @property(nonatomic, assign) int abc_lowerCamelCase; The corresponding style rule: https://developer.apple.com/library/content/qa/qa1908/_index.html objc-super-self Finds invocations of -self on super instances in initializers of sub- classes of NSObject and recommends calling a superclass initializer in- stead. Invoking -self on super instances in initializers is a common program- mer error when the programmer's original intent is to call a superclass initializer. Failing to call a superclass initializer breaks initial- izer chaining and can result in invalid object initialization. openmp-exception-escape Analyzes OpenMP Structured Blocks and checks that no exception escapes out of the Structured Block it was thrown in. As per the OpenMP specification, a structured block is an executable statement, possibly compound, with a single entry at the top and a sin- gle exit at the bottom. Which means, throw may not be used to 'exit' out of the structured block. If an exception is not caught in the same structured block it was thrown in, the behavior is undefined. FIXME: this check does not model SEH, setjmp/longjmp. WARNING! This check may be expensive on large source files. Options IgnoredExceptions Comma-separated list containing type names which are not counted as thrown exceptions in the check. Default value is an empty string. openmp-use-default-none Finds OpenMP directives that are allowed to contain a default clause, but either don't specify it or the clause is specified but with the kind other than none, and suggests to use the default(none) clause. Using default(none) clause forces developers to explicitly specify data sharing attributes for the variables referenced in the construct, thus making it obvious which variables are referenced, and what is their data sharing attribute, thus increasing readability and possibly making errors easier to spot. Example // ``for`` directive cannot have ``default`` clause, no diagnostics. void n0(const int a) { #pragma omp for for (int b = 0; b < a; b++) ; } // ``parallel`` directive. // ``parallel`` directive can have ``default`` clause, but said clause is not // specified, diagnosed. void p0_0() { #pragma omp parallel ; // WARNING: OpenMP directive ``parallel`` does not specify ``default`` // clause. Consider specifying ``default(none)`` clause. } // ``parallel`` directive can have ``default`` clause, and said clause is // specified, with ``none`` kind, all good. void p0_1() { #pragma omp parallel default(none) ; } // ``parallel`` directive can have ``default`` clause, and said clause is // specified, but with ``shared`` kind, which is not ``none``, diagnose. void p0_2() { #pragma omp parallel default(shared) ; // WARNING: OpenMP directive ``parallel`` specifies ``default(shared)`` // clause. Consider using ``default(none)`` clause instead. } // ``parallel`` directive can have ``default`` clause, and said clause is // specified, but with ``firstprivate`` kind, which is not ``none``, diagnose. void p0_3() { #pragma omp parallel default(firstprivate) ; // WARNING: OpenMP directive ``parallel`` specifies ``default(firstprivate)`` // clause. Consider using ``default(none)`` clause instead. } performance-avoid-endl Checks for uses of std::endl on streams and suggests using the newline character '\n' instead. Rationale: Using std::endl on streams can be less efficient than using the newline character '\n' because std::endl performs two operations: it writes a newline character to the output stream and then flushes the stream buffer. Writing a single newline character using '\n' does not trigger a flush, which can improve performance. In addition, flushing the stream buffer can cause additional overhead when working with streams that are buffered. Example: Consider the following code: #include <iostream> int main() { std::cout << "Hello" << std::endl; } Which gets transformed into: #include <iostream> int main() { std::cout << "Hello" << '\n'; } This code writes a single newline character to the std::cout stream without flushing the stream buffer. Additionally, it is important to note that the standard C++ streams (like std::cerr, std::wcerr, std::clog and std::wclog) always flush af- ter a write operation, unless std::ios_base::sync_with_stdio is set to false. regardless of whether std::endl or '\n' is used. Therefore, us- ing '\n' with these streams will not result in any performance gain, but it is still recommended to use '\n' for consistency and readabil- ity. If you do need to flush the stream buffer, you can use std::flush ex- plicitly like this: #include <iostream> int main() { std::cout << "Hello\n" << std::flush; } performance-enum-size Recommends the smallest possible underlying type for an enum or enum class based on the range of its enumerators. Analyzes the values of the enumerators in an enum or enum class, including signed values, to rec- ommend the smallest possible underlying type that can represent all the values of the enum. The suggested underlying types are the integral types std::uint8_t, std::uint16_t, and std::uint32_t for unsigned types, and std::int8_t, std::int16_t, and std::int32_t for signed types. Using the suggested underlying types can help reduce the memory footprint of the program and improve performance in some cases. For example: // BEFORE enum Color { RED = -1, GREEN = 0, BLUE = 1 }; std::optional<Color> color_opt; The Color enum uses the default underlying type, which is int in this case, and its enumerators have values of -1, 0, and 1. Additionally, the std::optional<Color> object uses 8 bytes due to padding (platform dependent). // AFTER enum Color : std:int8_t { RED = -1, GREEN = 0, BLUE = 1 } std::optional<Color> color_opt; In the revised version of the Color enum, the underlying type has been changed to std::int8_t. The enumerator RED has a value of -1, which can be represented by a signed 8-bit integer. By using a smaller underlying type, the memory footprint of the Color enum is reduced from 4 bytes to 1 byte. The revised version of the std::optional<Color> object would only require 2 bytes (due to lack of padding), since it contains a single byte for the Color enum and a sin- gle byte for the bool flag that indicates whether the optional value is set. Reducing the memory footprint of an enum can have significant benefits in terms of memory usage and cache performance. However, it's important to consider the trade-offs and potential impact on code readability and maintainability. Enums without enumerators (empty) are excluded from analysis. Requires C++11 or above. Does not provide auto-fixes. Options EnumIgnoreList Option is used to ignore certain enum types. It accepts a semi- colon-separated list of (fully qualified) enum type names or regular expressions that match the enum type names. The default value is an empty string, which means no enums will be ignored. performance-faster-string-find Optimize calls to std::string::find() and friends when the needle passed is a single character string literal. The character literal overload is more efficient. Examples: str.find("A"); // becomes str.find('A'); Options StringLikeClasses Semicolon-separated list of names of string-like classes. By de- fault only ::std::basic_string and ::std::basic_string_view are considered. The check will only consider member functions named find, rfind, find_first_of, find_first_not_of, find_last_of, or find_last_not_of within these classes. performance-for-range-copy Finds C++11 for ranges where the loop variable is copied in each itera- tion but it would suffice to obtain it by const reference. The check is only applied to loop variables of types that are expensive to copy which means they are not trivially copyable or have a non-triv- ial copy constructor or destructor. To ensure that it is safe to replace the copy with a const reference the following heuristic is employed: 1. The loop variable is const qualified. 2. The loop variable is not const, but only const methods or operators are invoked on it, or it is used as const reference or value argu- ment in constructors or function calls. Options WarnOnAllAutoCopies When true, warns on any use of auto as the type of the range-based for loop variable. Default is false. AllowedTypes A semicolon-separated list of names of types allowed to be copied in each iteration. Regular expressions are accepted, e.g. [Rr]ef(erence)?$ matches every type with suffix Ref, ref, Refer- ence and reference. The default is empty. If a name in the list contains the sequence :: it is matched against the qualified typename (i.e. namespace::Type, otherwise it is matched against only the type name (i.e. Type). performance-implicit-cast-in-loop This check has been renamed to performance-implicit-conversion-in-loop. performance-implicit-conversion-in-loop This warning appears in a range-based loop with a loop variable of const ref type where the type of the variable does not match the one returned by the iterator. This means that an implicit conversion hap- pens, which can for example result in expensive deep copies. Example: map<int, vector<string>> my_map; for (const pair<int, vector<string>>& p : my_map) {} // The iterator type is in fact pair<const int, vector<string>>, which means // that the compiler added a conversion, resulting in a copy of the vectors. The easiest solution is usually to use const auto& instead of writing the type manually. performance-inefficient-algorithm Warns on inefficient use of STL algorithms on associative containers. Associative containers implement some of the algorithms as methods which should be preferred to the algorithms in the algorithm header. The methods can take advantage of the order of the elements. std::set<int> s; auto it = std::find(s.begin(), s.end(), 43); // becomes auto it = s.find(43); std::set<int> s; auto c = std::count(s.begin(), s.end(), 43); // becomes auto c = s.count(43); performance-inefficient-string-concatenation This check warns about the performance overhead arising from concate- nating strings using the operator+, for instance: std::string a("Foo"), b("Bar"); a = a + b; Instead of this structure you should use operator+= or std::string's (std::basic_string) class member function append(). For instance: std::string a("Foo"), b("Baz"); for (int i = 0; i < 20000; ++i) { a = a + "Bar" + b; } Could be rewritten in a greatly more efficient way like: std::string a("Foo"), b("Baz"); for (int i = 0; i < 20000; ++i) { a.append("Bar").append(b); } And this can be rewritten too: void f(const std::string&) {} std::string a("Foo"), b("Baz"); void g() { f(a + "Bar" + b); } In a slightly more efficient way like: void f(const std::string&) {} std::string a("Foo"), b("Baz"); void g() { f(std::string(a).append("Bar").append(b)); } Options StrictMode When false, the check will only check the string usage in while, for and for-range statements. Default is false. performance-inefficient-vector-operation Finds possible inefficient std::vector operations (e.g. push_back, em- place_back) that may cause unnecessary memory reallocations. It can also find calls that add element to protobuf repeated field in a loop without calling Reserve() before the loop. Calling Reserve() first can avoid unnecessary memory reallocations. Currently, the check only detects following kinds of loops with a sin- gle statement body: • Counter-based for loops start with 0: std::vector<int> v; for (int i = 0; i < n; ++i) { v.push_back(n); // This will trigger the warning since the push_back may cause multiple // memory reallocations in v. This can be avoid by inserting a 'reserve(n)' // statement before the for statement. } SomeProto p; for (int i = 0; i < n; ++i) { p.add_xxx(n); // This will trigger the warning since the add_xxx may cause multiple memory // reallocations. This can be avoid by inserting a // 'p.mutable_xxx().Reserve(n)' statement before the for statement. } • For-range loops like for (range-declaration : range_expression), the type of range_expression can be std::vector, std::array, std::deque, std::set, std::unordered_set, std::map, std::unordered_set: std::vector<int> data; std::vector<int> v; for (auto element : data) { v.push_back(element); // This will trigger the warning since the 'push_back' may cause multiple // memory reallocations in v. This can be avoid by inserting a // 'reserve(data.size())' statement before the for statement. } Options VectorLikeClasses Semicolon-separated list of names of vector-like classes. By de- fault only ::std::vector is considered. EnableProto When true, the check will also warn on inefficient operations for proto repeated fields. Otherwise, the check only warns on inefficient vector operations. Default is false. performance-move-const-arg The check warns • if std::move() is called with a constant argument, • if std::move() is called with an argument of a trivially-copyable type, • if the result of std::move() is passed as a const reference argument. In all three cases, the check will suggest a fix that removes the std::move(). Here are examples of each of the three cases: const string s; return std::move(s); // Warning: std::move of the const variable has no effect int x; return std::move(x); // Warning: std::move of the variable of a trivially-copyable type has no effect void f(const string &s); string s; f(std::move(s)); // Warning: passing result of std::move as a const reference argument; no move will actually happen Options CheckTriviallyCopyableMove If true, enables detection of trivially copyable types that do not have a move constructor. Default is true. CheckMoveToConstRef If true, enables detection of std::move() passed as a const ref- erence argument. Default is true. performance-move-constructor-init "cert-oop11-cpp" redirects here as an alias for this check. The check flags user-defined move constructors that have a ctor-ini- tializer initializing a member or base class through a copy constructor instead of a move constructor. performance-no-automatic-move Finds local variables that cannot be automatically moved due to const- ness. Under certain conditions, local values are automatically moved out when returning from a function. A common mistake is to declare local lvalue variables const, which prevents the move. Example [1]: StatusOr<std::vector<int>> Cool() { std::vector<int> obj = ...; return obj; // calls StatusOr::StatusOr(std::vector<int>&&) } StatusOr<std::vector<int>> NotCool() { const std::vector<int> obj = ...; return obj; // calls `StatusOr::StatusOr(const std::vector<int>&)` } The former version (Cool) should be preferred over the latter (NotCool) as it will avoid allocations and potentially large memory copies. Semantics In the example above, StatusOr::StatusOr(T&&) have the same semantics as long as the copy and move constructors for T have the same seman- tics. Note that there is no guarantee that S::S(T&&) and S::S(const T&) have the same semantics for any single S, so we're not providing auto- mated fixes for this check, and judgement should be exerted when making the suggested changes. -Wreturn-std-move Another case where the move cannot happen is the following: StatusOr<std::vector<int>> Uncool() { std::vector<int>&& obj = ...; return obj; // calls `StatusOr::StatusOr(const std::vector<int>&)` } In that case the fix is more consensual: just return std::move(obj). This is handled by the -Wreturn-std-move warning. performance-no-int-to-ptr Diagnoses every integer to pointer cast. While casting an (integral) pointer to an integer is obvious - you just get the integral value of the pointer, casting an integer to an (inte- gral) pointer is deceivingly different. While you will get a pointer with that integral value, if you got that integral value via a pointer-to-integer cast originally, the new pointer will lack the provenance information from the original pointer. So while (integral) pointer to integer casts are effectively no-ops, and are transparent to the optimizer, integer to (integral) pointer casts are NOT transparent, and may conceal information from optimizer. While that may be the intention, it is not always so. For example, let's take a look at a routine to align the pointer up to the multiple of 16: The obvious, naive implementation for that is: char* src(char* maybe_underbiased_ptr) { uintptr_t maybe_underbiased_intptr = (uintptr_t)maybe_underbiased_ptr; uintptr_t aligned_biased_intptr = maybe_underbiased_intptr + 15; uintptr_t aligned_intptr = aligned_biased_intptr & (~15); return (char*)aligned_intptr; // warning: avoid integer to pointer casts [performance-no-int-to-ptr] } The check will rightfully diagnose that cast. But when provenance concealment is not the goal of the code, but an ac- cident, this example can be rewritten as follows, without using integer to pointer cast: char* tgt(char* maybe_underbiased_ptr) { uintptr_t maybe_underbiased_intptr = (uintptr_t)maybe_underbiased_ptr; uintptr_t aligned_biased_intptr = maybe_underbiased_intptr + 15; uintptr_t aligned_intptr = aligned_biased_intptr & (~15); uintptr_t bias = aligned_intptr - maybe_underbiased_intptr; return maybe_underbiased_ptr + bias; } performance-noexcept-destructor The check flags user-defined destructors marked with noexcept(expr) where expr evaluates to false (but is not a false literal itself). When a destructor is marked as noexcept, it assures the compiler that no exceptions will be thrown during the destruction of an object, which allows the compiler to perform certain optimizations such as omitting exception handling code. performance-noexcept-move-constructor The check flags user-defined move constructors and assignment operators not marked with noexcept or marked with noexcept(expr) where expr eval- uates to false (but is not a false literal itself). Move constructors of all the types used with STL containers, for exam- ple, need to be declared noexcept. Otherwise STL will choose copy con- structors instead. The same is valid for move assignment operations. performance-noexcept-swap The check flags user-defined swap and iter_swap functions not marked with noexcept or marked with noexcept(expr) where expr evaluates to false (but is not a false literal itself). When a swap or iter_swap function is marked as noexcept, it assures the compiler that no exceptions will be thrown during the swapping of two objects, which allows the compiler to perform certain optimizations such as omitting exception handling code. performance-trivially-destructible Finds types that could be made trivially-destructible by removing out-of-line defaulted destructor declarations. struct A: TrivialType { ~A(); // Makes A non-trivially-destructible. TrivialType trivial_fields; }; A::~A() = default; performance-type-promotion-in-math-fn Finds calls to C math library functions (from math.h or, in C++, cmath) with implicit float to double promotions. For example, warns on ::sin(0.f), because this function's parameter is a double. You probably meant to call std::sin(0.f) (in C++), or sinf(0.f) (in C). float a; asin(a); // becomes float a; std::asin(a); performance-unnecessary-copy-initialization Finds local variable declarations that are initialized using the copy constructor of a non-trivially-copyable type but it would suffice to obtain a const reference. The check is only applied if it is safe to replace the copy by a const reference. This is the case when the variable is const qualified or when it is only used as a const, i.e. only const methods or operators are invoked on it, or it is used as const reference or value argument in constructors or function calls. Example: const string& constReference(); void Function() { // The warning will suggest making this a const reference. const string UnnecessaryCopy = constReference(); } struct Foo { const string& name() const; }; void Function(const Foo& foo) { // The warning will suggest making this a const reference. string UnnecessaryCopy1 = foo.name(); UnnecessaryCopy1.find("bar"); // The warning will suggest making this a const reference. string UnnecessaryCopy2 = UnnecessaryCopy1; UnnecessaryCopy2.find("bar"); } Options AllowedTypes A semicolon-separated list of names of types allowed to be ini- tialized by copying. Regular expressions are accepted, e.g. [Rr]ef(erence)?$ matches every type with suffix Ref, ref, Refer- ence and reference. The default is empty. If a name in the list contains the sequence :: it is matched against the qualified typename (i.e. namespace::Type, otherwise it is matched against only the type name (i.e. Type). ExcludedContainerTypes A semicolon-separated list of names of types whose methods are allowed to return the const reference the variable is copied from. When an expensive to copy variable is copy initialized by the return value from a type on this list the check does not trigger. This can be used to exclude types known to be const in- correct or where the lifetime or immutability of returned refer- ences is not tied to mutations of the container. An example are view types that don't own the underlying data. Like for Allowed- Types above, regular expressions are accepted and the inclusion of :: determines whether the qualified typename is matched or not. performance-unnecessary-value-param Flags value parameter declarations of expensive to copy types that are copied for each invocation but it would suffice to pass them by const reference. The check is only applied to parameters of types that are expensive to copy which means they are not trivially copyable or have a non-trivial copy constructor or destructor. To ensure that it is safe to replace the value parameter with a const reference the following heuristic is employed: 1. the parameter is const qualified; 2. the parameter is not const, but only const methods or operators are invoked on it, or it is used as const reference or value argument in constructors or function calls. Example: void f(const string Value) { // The warning will suggest making Value a reference. } void g(ExpensiveToCopy Value) { // The warning will suggest making Value a const reference. Value.ConstMethd(); ExpensiveToCopy Copy(Value); } If the parameter is not const, only copied or assigned once and has a non-trivial move-constructor or move-assignment operator respectively the check will suggest to move it. Example: void setValue(string Value) { Field = Value; } Will become: #include <utility> void setValue(string Value) { Field = std::move(Value); } Options IncludeStyle A string specifying which include-style is used, llvm or google. Default is llvm. AllowedTypes A semicolon-separated list of names of types allowed to be passed by value. Regular expressions are accepted, e.g. [Rr]ef(erence)?$ matches every type with suffix Ref, ref, Refer- ence and reference. The default is empty. If a name in the list contains the sequence :: it is matched against the qualified typename (i.e. namespace::Type, otherwise it is matched against only the type name (i.e. Type). portability-restrict-system-includes Checks to selectively allow or disallow a configurable list of system headers. For example: In order to only allow zlib.h from the system you would set the options to -*,zlib.h. #include <curses.h> // Bad: disallowed system header. #include <openssl/ssl.h> // Bad: disallowed system header. #include <zlib.h> // Good: allowed system header. #include "src/myfile.h" // Good: non-system header always allowed. In order to allow everything except zlib.h from the system you would set the options to *,-zlib.h. #include <curses.h> // Good: allowed system header. #include <openssl/ssl.h> // Good: allowed system header. #include <zlib.h> // Bad: disallowed system header. #include "src/myfile.h" // Good: non-system header always allowed. Since the options support globbing you can use wildcarding to allow groups of headers. -*,openssl/*.h will allow all openssl headers but disallow any others. #include <curses.h> // Bad: disallowed system header. #include <openssl/ssl.h> // Good: allowed system header. #include <openssl/rsa.h> // Good: allowed system header. #include <zlib.h> // Bad: disallowed system header. #include "src/myfile.h" // Good: non-system header always allowed. Options Includes A string containing a comma separated glob list of allowed in- clude filenames. Similar to the -checks glob list for running clang-tidy itself, the two wildcard characters are * and -, to include and exclude globs, respectively. The default is *, which allows all includes. portability-simd-intrinsics Finds SIMD intrinsics calls and suggests std::experimental::simd (- P0214) alternatives. If the option Suggest is set to true, for _mm_add_epi32(a, b); // x86 vec_add(a, b); // Power the check suggests an alternative: operator+ on std::experimental::simd objects. Otherwise, it just complains the intrinsics are non-portable (and there are P0214 alternatives). Many architectures provide SIMD operations (e.g. x86 SSE/AVX, Power Al- tiVec/VSX, ARM NEON). It is common that SIMD code implementing the same algorithm, is written in multiple target-dispatching pieces to optimize for different architectures or micro-architectures. The C++ standard proposal P0214 and its extensions cover many common SIMD operations. By migrating from target-dependent intrinsics to P0214 operations, the SIMD code can be simplified and pieces for different targets can be unified. Refer to P0214 for introduction and motivation for the data-parallel standard library. Options Suggest If this option is set to true (default is false), the check will suggest P0214 alternatives, otherwise it only points out the in- trinsic function is non-portable. Std The namespace used to suggest P0214 alternatives. If not speci- fied, std:: for -std=c++20 and std::experimental:: for -std=c++11. portability-std-allocator-const Report use of std::vector<const T> (and similar containers of const el- ements). These are not allowed in standard C++, and should usually be std::vector<T> instead." Per C++ [allocator.requirements.general]: "T is any cv-unqualified ob- ject type", std::allocator<const T> is undefined. Many standard con- tainers use std::allocator by default and therefore their const T in- stantiations are undefined. libc++ defines std::allocator<const T> as an extension which will be removed in the future. libstdc++ and MSVC do not support std::allocator<const T>: // libstdc++ has a better diagnostic since https://gcc.gnu.org/bugzilla/show_bug.cgi?id=48101 std::deque<const int> deque; // error: static assertion failed: std::deque must have a non-const, non-volatile value_type std::set<const int> set; // error: static assertion failed: std::set must have a non-const, non-volatile value_type std::vector<int* const> vector; // error: static assertion failed: std::vector must have a non-const, non-volatile value_type // MSVC // error C2338: static_assert failed: 'The C++ Standard forbids containers of const elements because allocator<const T> is ill-formed.' Code bases only compiled with libc++ may accrue such undefined usage. This check finds such code and prevents backsliding while clean-up is ongoing. readability-avoid-const-params-in-decls Checks whether a function declaration has parameters that are top level const. const values in declarations do not affect the signature of a function, so they should not be put there. Examples: void f(const string); // Bad: const is top level. void f(const string&); // Good: const is not top level. Options IgnoreMacros If set to true, the check will not give warnings inside macros. Default is true. readability-avoid-nested-conditional-operator Identifies instances of nested conditional operators in the code. Nested conditional operators, also known as ternary operators, can con- tribute to reduced code readability and comprehension. So they should be split as several statements and stored the intermediate results in temporary variable. Examples: int NestInConditional = (condition1 ? true1 : false1) ? true2 : false2; int NestInTrue = condition1 ? (condition2 ? true1 : false1) : false2; int NestInFalse = condition1 ? true1 : condition2 ? true2 : false1; This check implements part of AUTOSAR C++14 Rule A5-16-1. readability-avoid-return-with-void-value Finds return statements with void values used within functions with void result types. A function with a void return type is intended to perform a task with- out producing a return value. Return statements with expressions could lead to confusion and may miscommunicate the function's intended behav- ior. Example: void g(); void f() { // ... return g(); } In a long function body, the return statement suggests that the func- tion returns a value. However, return g(); is a combination of two statements that should be written as g(); return; to make clear that g() is called and immediately afterwards the func- tion returns (nothing). In C, the same issue is detected by the compiler if the -Wpedantic mode is enabled. Options IgnoreMacros The value false specifies that return statements expanded from macros are not checked. The default value is true. StrictMode The value false specifies that a direct return statement shall be excluded from the analysis if it is the only statement not contained in a block like if (cond) return g();. The default value is true. readability-avoid-unconditional-preprocessor-if Finds code blocks that are constantly enabled or disabled in preproces- sor directives by analyzing #if conditions, such as #if 0 and #if 1, etc. #if 0 // some disabled code #endif #if 1 // some enabled code that can be disabled manually #endif Unconditional preprocessor directives, such as #if 0 for disabled code and #if 1 for enabled code, can lead to dead code and always enabled code, respectively. Dead code can make understanding the codebase more difficult, hinder readability, and may be a sign of unfinished func- tionality or abandoned features. This can cause maintenance issues, confusion for future developers, and potential compilation problems. As a solution for both cases, consider using preprocessor macros or de- fines, like #ifdef DEBUGGING_ENABLED, to control code enabling or dis- abling. This approach provides better coordination and flexibility when working with different parts of the codebase. Alternatively, you can comment out the entire code using /* */ block comments and add a hint, such as @todo, to indicate future actions. readability-braces-around-statements google-readability-braces-around-statements redirects here as an alias for this check. Checks that bodies of if statements and loops (for, do while, and while) are inside braces. Before: if (condition) statement; After: if (condition) { statement; } Options ShortStatementLines Defines the minimal number of lines that the statement should have in order to trigger this check. The number of lines is counted from the end of condition or ini- tial keyword (do/else) until the last line of the inner state- ment. Default value 0 means that braces will be added to all statements (not having them already). readability-const-return-type Checks for functions with a const-qualified return type and recommends removal of the const keyword. Such use of const is usually superfluous, and can prevent valuable compiler optimizations. Does not (yet) fix trailing return types. Examples: const int foo(); const Clazz foo(); Clazz *const foo(); Note that this applies strictly to top-level qualification, which ex- cludes pointers or references to const values. For example, these are fine: const int* foo(); const int& foo(); const Clazz* foo(); Options IgnoreMacros If set to true, the check will not give warnings inside macros. Default is true. readability-container-contains Finds usages of container.count() and container.find() == con- tainer.end() which should be replaced by a call to the container.con- tains() method introduced in C++ 20. Whether an element is contained inside a container should be checked with contains instead of count/find because contains conveys the intent more clearly. Furthermore, for containers which permit multiple entries per key (multimap, multiset, ...), contains is more efficient than count because count has to do unnecessary additional work. Examples: +----------------------------+----------------------------+ | Initial expression | Result | +----------------------------+----------------------------+ | myMap.find(x) == | !myMap.contains(x) | | myMap.end() | | +----------------------------+----------------------------+ | myMap.find(x) != | myMap.contains(x) | | myMap.end() | | +----------------------------+----------------------------+ | if (myMap.count(x)) | if (myMap.contains(x)) | +----------------------------+----------------------------+ | bool exists = | bool exists = myMap.con- | | myMap.count(x) | tains(x) | +----------------------------+----------------------------+ | bool exists = | bool exists = myMap.con- | | myMap.count(x) > 0 | tains(x) | +----------------------------+----------------------------+ | bool exists = | bool exists = myMap.con- | | myMap.count(x) >= 1 | tains(x) | +----------------------------+----------------------------+ | bool missing = | bool missing = !myMap.con- | | myMap.count(x) == 0 | tains(x) | +----------------------------+----------------------------+ This check applies to std::set, std::unordered_set, std::map, std::un- ordered_map and the corresponding multi-key variants. It is only ac- tive for C++20 and later, as the contains method was only added in C++20. readability-container-data-pointer Finds cases where code could use data() rather than the address of the element at index 0 in a container. This pattern is commonly used to ma- terialize a pointer to the backing data of a container. std::vector and std::string provide a data() accessor to retrieve the data pointer which should be preferred. This also ensures that in the case that the container is empty, the data pointer access does not perform an errant memory access. Options IgnoredContainers Semicolon-separated list of containers regexp for which this check won't be enforced. Default is empty. readability-container-size-empty Checks whether a call to the size()/length() method can be replaced with a call to empty(). The emptiness of a container should be checked using the empty() method instead of the size()/length() method. It is not guaranteed that size()/length() is a constant-time function, and it is generally more efficient and also shows clearer intent to use empty(). Furthermore some containers may implement the empty() method but not implement the size() or length() method. Using empty() whenever possible makes it easier to switch to another container in the future. The check issues warning if a container has empty() and size() or length() methods matching following signatures: size_type size() const; size_type length() const; bool empty() const; size_type can be any kind of integer type. ExcludedComparisonTypes A semicolon-separated list of class names for which the check will ignore comparisons of objects with default-constructed ob- jects of the same type. If a class is listed here, the check will not suggest using empty() instead of such comparisons for objects of that class. Default value is: ::std::array. readability-convert-member-functions-to-static Finds non-static member functions that can be made static because the functions don't use this. After applying modifications as suggested by the check, running the check again might find more opportunities to mark member functions sta- tic. After making a member function static, you might want to run the check readability-static-accessed-through-instance to replace calls like In- stance.method() by Class::method(). readability-delete-null-pointer Checks the if statements where a pointer's existence is checked and then deletes the pointer. The check is unnecessary as deleting a null pointer has no effect. int *p; if (p) delete p; readability-duplicate-include Looks for duplicate includes and removes them. The check maintains a list of included files and looks for duplicates. If a macro is defined or undefined then the list of included files is cleared. Examples: #include <memory> #include <vector> #include <memory> becomes #include <memory> #include <vector> Because of the intervening macro definitions, this code remains un- changed: #undef NDEBUG #include "assertion.h" // ...code with assertions enabled #define NDEBUG #include "assertion.h" // ...code with assertions disabled readability-else-after-return LLVM Coding Standards advises to reduce indentation where possible and where it makes understanding code easier. Early exit is one of the suggested enforcements of that. Please do not use else or else if after something that interrupts control flow - like return, break, continue, throw. The following piece of code illustrates how the check works. This piece of code: void foo(int Value) { int Local = 0; for (int i = 0; i < 42; i++) { if (Value == 1) { return; } else { Local++; } if (Value == 2) continue; else Local++; if (Value == 3) { throw 42; } else { Local++; } } } Would be transformed into: void foo(int Value) { int Local = 0; for (int i = 0; i < 42; i++) { if (Value == 1) { return; } Local++; if (Value == 2) continue; Local++; if (Value == 3) { throw 42; } Local++; } } Options WarnOnUnfixable When true, emit a warning for cases where the check can't output a Fix-It. These can occur with declarations inside the else branch that would have an extended lifetime if the else branch was removed. Default value is true. WarnOnConditionVariables When true, the check will attempt to refactor a variable defined inside the condition of the if statement that is used in the else branch defining them just before the if statement. This can only be done if the if statement is the last statement in its parent's scope. Default value is true. LLVM alias There is an alias of this check called llvm-else-after-return. In that version the options WarnOnUnfixable and WarnOnConditionVariables are both set to false by default. This check helps to enforce this LLVM Coding Standards recommendation. readability-function-cognitive-complexity Checks function Cognitive Complexity metric. The metric is implemented as per the COGNITIVE COMPLEXITY by Sonar- Source specification version 1.2 (19 April 2017). Options Threshold Flag functions with Cognitive Complexity exceeding this number. The default is 25. DescribeBasicIncrements If set to true, then for each function exceeding the complexity threshold the check will issue additional diagnostics on every piece of code (loop, if statement, etc.) which contributes to that complexity. See also the examples below. Default is true. IgnoreMacros If set to true, the check will ignore code inside macros. Note, that also any macro arguments are ignored, even if they should count to the complexity. As this might change in the future, this option isn't guaranteed to be forward-compatible. Default is false. Building blocks There are three basic building blocks of a Cognitive Complexity metric: Increment The following structures increase the function's Cognitive Complexity metric (by 1): • Conditional operators: • if() • else if() • else • cond ? true : false • switch() • Loops: • for() • C++11 range-based for() • while() • do while() • catch () • goto LABEL, goto *(&&LABEL)), • sequences of binary logical operators: • boolean1 || boolean2 • boolean1 && boolean2 Nesting level While by itself the nesting level does not change the function's Cogni- tive Complexity metric, it is tracked, and is used by the next, third building block. The following structures increase the nesting level (by 1): • Conditional operators: • if() • else if() • else • cond ? true : false • switch() • Loops: • for() • C++11 range-based for() • while() • do while() • catch () • Nested functions: • C++11 Lambda • Nested class • Nested struct • GNU statement expression • Apple Block Declaration Nesting increment This is where the previous basic building block, Nesting level, mat- ters. The following structures increase the function's Cognitive Com- plexity metric by the current Nesting level: • Conditional operators: • if() • cond ? true : false • switch() • Loops: • for() • C++11 range-based for() • while() • do while() • catch () Examples The simplest case. This function has Cognitive Complexity of 0. void function0() {} Slightly better example. This function has Cognitive Complexity of 1. int function1(bool var) { if(var) // +1, nesting level +1 return 42; return 0; } Full example. This function has Cognitive Complexity of 3. int function3(bool var1, bool var2) { if(var1) { // +1, nesting level +1 if(var2) // +2 (1 + current nesting level of 1), nesting level +1 return 42; } return 0; } In the last example, the check will flag function3 if the option Threshold is set to 2 or smaller. If the option DescribeBasicIncrements is set to true, it will additionally flag the two if statements with the amounts by which they increase to the complexity of the function and the current nesting level. Limitations The metric is implemented with two notable exceptions: • preprocessor conditionals (#ifdef, #if, #elif, #else, #endif) are not accounted for. • each method in a recursion cycle is not accounted for. It can't be fully implemented, because cross-translational-unit analysis would be needed, which is currently not possible in clang-tidy. readability-function-size google-readability-function-size redirects here as an alias for this check. Checks for large functions based on various metrics. Options LineThreshold Flag functions exceeding this number of lines. The default is none (ignore the number of lines). StatementThreshold Flag functions exceeding this number of statements. This may differ significantly from the number of lines for macro-heavy code. The default is 800. BranchThreshold Flag functions exceeding this number of control statements. The default is none (ignore the number of branches). ParameterThreshold Flag functions that exceed a specified number of parameters. The default is none (ignore the number of parameters). NestingThreshold Flag compound statements which create next nesting level after NestingThreshold. This may differ significantly from the ex- pected value for macro-heavy code. The default is none (ignore the nesting level). VariableThreshold Flag functions exceeding this number of variables declared in the body. The default is none (ignore the number of variables). Please note that function parameters and variables declared in lambdas, GNU Statement Expressions, and nested class inline functions are not counted. readability-identifier-length This check finds variables and function parameters whose length are too short. The desired name length is configurable. Special cases are supported for loop counters and for exception vari- able names. Options The following options are described below: • MinimumVariableNameLength, IgnoredVariableNames • MinimumParameterNameLength, IgnoredParameterNames • MinimumLoopCounterNameLength, IgnoredLoopCounterNames • MinimumExceptionNameLength, IgnoredExceptionVariableNames MinimumVariableNameLength All variables (other than loop counter, exception names and function parameters) are expected to have at least a length of MinimumVariableNameLength (default is 3). Setting it to 0 or 1 disables the check entirely. int doubler(int x) // warns that x is too short { return 2 * x; } This check does not have any fix suggestions in the general case since variable names have semantic value. IgnoredVariableNames Specifies a regular expression for variable names that are to be ignored. The default value is empty, thus no names are ignored. MinimumParameterNameLength All function parameter names are expected to have a length of at least MinimumParameterNameLength (default is 3). Setting it to 0 or 1 disables the check entirely. int i = 42; // warns that 'i' is too short This check does not have any fix suggestions in the general case since variable names have semantic value. IgnoredParameterNames Specifies a regular expression for parameters that are to be ig- nored. The default value is ^[n]$ for historical reasons. MinimumLoopCounterNameLength Loop counter variables are expected to have a length of at least MinimumLoopCounterNameLength characters (default is 2). Setting it to 0 or 1 disables the check entirely. // This warns that 'q' is too short. for (int q = 0; q < size; ++ q) { // ... } IgnoredLoopCounterNames Specifies a regular expression for counter names that are to be ignored. The default value is ^[ijk_]$; the first three symbols for historical reasons and the last one since it is frequently used as a "don't care" value, specifically in tools such as Google Benchmark. // This does not warn by default, for historical reasons. for (int i = 0; i < size; ++ i) { // ... } MinimumExceptionNameLength Exception clause variables are expected to have a length of at least MinimumExceptionNameLength (default is 2). Setting it to 0 or 1 disables the check entirely. try { // ... } // This warns that 'e' is too short. catch (const std::exception& x) { // ... } IgnoredExceptionVariableNames Specifies a regular expression for exception variable names that are to be ignored. The default value is ^[e]$ mainly for histor- ical reasons. try { // ... } // This does not warn by default, for historical reasons. catch (const std::exception& e) { // ... } readability-identifier-naming Checks for identifiers naming style mismatch. This check will try to enforce coding guidelines on the identifiers naming. It supports one of the following casing types and tries to con- vert from one to another if a mismatch is detected Casing types include: • lower_case, • UPPER_CASE, • camelBack, • CamelCase, • camel_Snake_Back, • Camel_Snake_Case, • aNy_CasE, • Leading_upper_snake_case. It also supports a fixed prefix and suffix that will be prepended or appended to the identifiers, regardless of the casing. Many configuration options are available, in order to be able to create different rules for different kinds of identifiers. In general, the rules are falling back to a more generic rule if the specific case is not configured. The naming of virtual methods is reported where they occur in the base class, but not where they are overridden, as it can't be fixed locally there. This also applies for pseudo-override patterns like CRTP. Leading_upper_snake_case is a naming convention where the first word is capitalized followed by lower case word(s) seperated by underscore(s) '_'. Examples include: Cap_snake_case, Cobra_case, Foo_bar_baz, and Master_copy_8gb. Options The following options are described below: • AbstractClassCase, AbstractClassPrefix, AbstractClassSuffix, AbstractClassIgnoredRegexp, AbstractClassHungarianPrefix • AggressiveDependentMemberLookup • CheckAnonFieldInParent • ClassCase, ClassPrefix, ClassSuffix, ClassIgnoredRegexp, ClassHungarianPrefix • ClassConstantCase, ClassConstantPrefix, ClassConstantSuffix, ClassConstantIgnoredRegexp, ClassConstantHungarianPrefix • ClassMemberCase, ClassMemberPrefix, ClassMemberSuffix, ClassMemberIgnoredRegexp, ClassMemberHungarianPrefix • ClassMethodCase, ClassMethodPrefix, ClassMethodSuffix, ClassMethodIgnoredRegexp • ConceptCase, ConceptPrefix, ConceptSuffix, ConceptIgnoredRegexp • ConstantCase, ConstantPrefix, ConstantSuffix, ConstantIgnoredRegexp, ConstantHungarianPrefix • ConstantMemberCase, ConstantMemberPrefix, ConstantMemberSuffix, ConstantMemberIgnoredRegexp, ConstantMemberHungarianPrefix • ConstantParameterCase, ConstantParameterPrefix, ConstantParameterSuffix, ConstantParameterIgnoredRegexp, ConstantParameterHungarianPrefix • ConstantPointerParameterCase, ConstantPointerParameterPrefix, ConstantPointerParameterSuffix, ConstantPointerParameterIgnoredRegexp, ConstantPointerParameterHungarianPrefix • ConstexprFunctionCase, ConstexprFunctionPrefix, ConstexprFunctionSuffix, ConstexprFunctionIgnoredRegexp • ConstexprMethodCase, ConstexprMethodPrefix, ConstexprMethodSuffix, ConstexprMethodIgnoredRegexp • ConstexprVariableCase, ConstexprVariablePrefix, ConstexprVariableSuffix, ConstexprVariableIgnoredRegexp, ConstexprVariableHungarianPrefix • EnumCase, EnumPrefix, EnumSuffix, EnumIgnoredRegexp • EnumConstantCase, EnumConstantPrefix, EnumConstantSuffix, EnumConstantIgnoredRegexp, EnumConstantHungarianPrefix • FunctionCase, FunctionPrefix, FunctionSuffix, FunctionIgnoredRegexp • GetConfigPerFile • GlobalConstantCase, GlobalConstantPrefix, GlobalConstantSuffix, GlobalConstantIgnoredRegexp, GlobalConstantHungarianPrefix • GlobalConstantPointerCase, GlobalConstantPointerPrefix, GlobalConstantPointerSuffix, GlobalConstantPointerIgnoredRegexp, GlobalConstantPointerHungarianPrefix • GlobalFunctionCase, GlobalFunctionPrefix, GlobalFunctionSuffix, GlobalFunctionIgnoredRegexp • GlobalPointerCase, GlobalPointerPrefix, GlobalPointerSuffix, GlobalPointerIgnoredRegexp, GlobalPointerHungarianPrefix • GlobalVariableCase, GlobalVariablePrefix, GlobalVariableSuffix, GlobalVariableIgnoredRegexp, GlobalVariableHungarianPrefix • IgnoreMainLikeFunctions • InlineNamespaceCase, InlineNamespacePrefix, InlineNamespaceSuffix, InlineNamespaceIgnoredRegexp • LocalConstantCase, LocalConstantPrefix, LocalConstantSuffix, LocalConstantIgnoredRegexp, LocalConstantHungarianPrefix • LocalConstantPointerCase, LocalConstantPointerPrefix, LocalConstantPointerSuffix, LocalConstantPointerIgnoredRegexp, LocalConstantPointerHungarianPrefix • LocalPointerCase, LocalPointerPrefix, LocalPointerSuffix, LocalPointerIgnoredRegexp, LocalPointerHungarianPrefix • LocalVariableCase, LocalVariablePrefix, LocalVariableSuffix, LocalVariableIgnoredRegexp, LocalVariableHungarianPrefix • MacroDefinitionCase, MacroDefinitionPrefix, MacroDefinitionSuffix, MacroDefinitionIgnoredRegexp • MemberCase, MemberPrefix, MemberSuffix, MemberIgnoredRegexp, MemberHungarianPrefix • MethodCase, MethodPrefix, MethodSuffix, MethodIgnoredRegexp • NamespaceCase, NamespacePrefix, NamespaceSuffix, NamespaceIgnoredRegexp • ParameterCase, ParameterPrefix, ParameterSuffix, ParameterIgnoredRegexp, ParameterHungarianPrefix • ParameterPackCase, ParameterPackPrefix, ParameterPackSuffix, ParameterPackIgnoredRegexp • PointerParameterCase, PointerParameterPrefix, PointerParameterSuffix, PointerParameterIgnoredRegexp, PointerParameterHungarianPrefix • PrivateMemberCase, PrivateMemberPrefix, PrivateMemberSuffix, PrivateMemberIgnoredRegexp, PrivateMemberHungarianPrefix • PrivateMethodCase, PrivateMethodPrefix, PrivateMethodSuffix, PrivateMethodIgnoredRegexp • ProtectedMemberCase, ProtectedMemberPrefix, ProtectedMemberSuffix, ProtectedMemberIgnoredRegexp, ProtectedMemberHungarianPrefix • ProtectedMethodCase, ProtectedMethodPrefix, ProtectedMethodSuffix, ProtectedMethodIgnoredRegexp • PublicMemberCase, PublicMemberPrefix, PublicMemberSuffix, PublicMemberIgnoredRegexp, PublicMemberHungarianPrefix • PublicMethodCase, PublicMethodPrefix, PublicMethodSuffix, PublicMethodIgnoredRegexp • ScopedEnumConstantCase, ScopedEnumConstantPrefix, ScopedEnumConstantSuffix, ScopedEnumConstantIgnoredRegexp • StaticConstantCase, StaticConstantPrefix, StaticConstantSuffix, StaticConstantIgnoredRegexp, StaticConstantHungarianPrefix • StaticVariableCase, StaticVariablePrefix, StaticVariableSuffix, StaticVariableIgnoredRegexp, StaticVariableHungarianPrefix • StructCase, StructPrefix, StructSuffix, StructIgnoredRegexp • TemplateParameterCase, TemplateParameterPrefix, TemplateParameterSuffix, TemplateParameterIgnoredRegexp • TemplateTemplateParameterCase, TemplateTemplateParameterPrefix, TemplateTemplateParameterSuffix, TemplateTemplateParameterIgnoredRegexp • TypeAliasCase, TypeAliasPrefix, TypeAliasSuffix, TypeAliasIgnoredRegexp • TypedefCase, TypedefPrefix, TypedefSuffix, TypedefIgnoredRegexp • TypeTemplateParameterCase, TypeTemplateParameterPrefix, TypeTemplateParameterSuffix, TypeTemplateParameterIgnoredRegexp • UnionCase, UnionPrefix, UnionSuffix, UnionIgnoredRegexp • ValueTemplateParameterCase, ValueTemplateParameterPrefix, ValueTemplateParameterSuffix, ValueTemplateParameterIgnoredRegexp • VariableCase, VariablePrefix, VariableSuffix, VariableIgnoredRegexp, VariableHungarianPrefix • VirtualMethodCase, VirtualMethodPrefix, VirtualMethodSuffix, VirtualMethodIgnoredRegexp AbstractClassCase When defined, the check will ensure abstract class names conform to the selected casing. AbstractClassPrefix When defined, the check will ensure abstract class names will add the prefixed with the given value (regardless of casing). AbstractClassIgnoredRegexp Identifier naming checks won't be enforced for abstract class names matching this regular expression. AbstractClassSuffix When defined, the check will ensure abstract class names will add the suffix with the given value (regardless of casing). AbstractClassHungarianPrefix When enabled, the check ensures that the declared identifier will have a Hungarian notation prefix based on the declared type. For example using values of: • AbstractClassCase of lower_case • AbstractClassPrefix of pre_ • AbstractClassSuffix of _post • AbstractClassHungarianPrefix of On Identifies and/or transforms abstract class names as follows: Before: class ABSTRACT_CLASS { public: ABSTRACT_CLASS(); }; After: class pre_abstract_class_post { public: pre_abstract_class_post(); }; AggressiveDependentMemberLookup When set to true the check will look in dependent base classes for dependent member references that need changing. This can lead to errors with template specializations so the default value is false. For example using values of: • ClassMemberCase of lower_case Before: template <typename T> struct Base { T BadNamedMember; }; template <typename T> struct Derived : Base<T> { void reset() { this->BadNamedMember = 0; } }; After if AggressiveDependentMemberLookup is false: template <typename T> struct Base { T bad_named_member; }; template <typename T> struct Derived : Base<T> { void reset() { this->BadNamedMember = 0; } }; After if AggressiveDependentMemberLookup is true: template <typename T> struct Base { T bad_named_member; }; template <typename T> struct Derived : Base<T> { void reset() { this->bad_named_member = 0; } }; CheckAnonFieldInParent When set to true, fields in anonymous records (i.e. anonymous unions and structs) will be treated as names in the enclosing scope rather than public members of the anonymous record for the purpose of name checking. For example: class Foo { private: union { int iv_; float fv_; }; }; If CheckAnonFieldInParent is false, you may get warnings that iv_ and fv_ are not coherent to public member names, because iv_ and fv_ are public members of the anonymous union. When CheckAnonFieldInParent is true, iv_ and fv_ will be treated as private data members of Foo for the purpose of name checking and thus no warnings will be emitted. ClassCase When defined, the check will ensure class names conform to the selected casing. ClassPrefix When defined, the check will ensure class names will add the prefixed with the given value (regardless of casing). ClassIgnoredRegexp Identifier naming checks won't be enforced for class names matching this regular expression. ClassSuffix When defined, the check will ensure class names will add the suffix with the given value (regardless of casing). ClassHungarianPrefix When enabled, the check ensures that the declared identifier will have a Hungarian notation prefix based on the declared type. For example using values of: • ClassCase of lower_case • ClassPrefix of pre_ • ClassSuffix of _post • ClassHungarianPrefix of On Identifies and/or transforms class names as follows: Before: class FOO { public: FOO(); ~FOO(); }; After: class pre_foo_post { public: pre_foo_post(); ~pre_foo_post(); }; ClassConstantCase When defined, the check will ensure class constant names conform to the selected casing. ClassConstantPrefix When defined, the check will ensure class constant names will add the prefixed with the given value (regardless of casing). ClassConstantIgnoredRegexp Identifier naming checks won't be enforced for class constant names matching this regular expression. ClassConstantSuffix When defined, the check will ensure class constant names will add the suffix with the given value (regardless of casing). ClassConstantHungarianPrefix When enabled, the check ensures that the declared identifier will have a Hungarian notation prefix based on the declared type. For example using values of: • ClassConstantCase of lower_case • ClassConstantPrefix of pre_ • ClassConstantSuffix of _post • ClassConstantHungarianPrefix of On Identifies and/or transforms class constant names as follows: Before: class FOO { public: static const int CLASS_CONSTANT; }; After: class FOO { public: static const int pre_class_constant_post; }; ClassMemberCase When defined, the check will ensure class member names conform to the selected casing. ClassMemberPrefix When defined, the check will ensure class member names will add the prefixed with the given value (regardless of casing). ClassMemberIgnoredRegexp Identifier naming checks won't be enforced for class member names matching this regular expression. ClassMemberSuffix When defined, the check will ensure class member names will add the suffix with the given value (regardless of casing). ClassMemberHungarianPrefix When enabled, the check ensures that the declared identifier will have a Hungarian notation prefix based on the declared type. For example using values of: • ClassMemberCase of lower_case • ClassMemberPrefix of pre_ • ClassMemberSuffix of _post • ClassMemberHungarianPrefix of On Identifies and/or transforms class member names as follows: Before: class FOO { public: static int CLASS_CONSTANT; }; After: class FOO { public: static int pre_class_constant_post; }; ClassMethodCase When defined, the check will ensure class method names conform to the selected casing. ClassMethodPrefix When defined, the check will ensure class method names will add the prefixed with the given value (regardless of casing). ClassMethodIgnoredRegexp Identifier naming checks won't be enforced for class method names matching this regular expression. ClassMethodSuffix When defined, the check will ensure class method names will add the suffix with the given value (regardless of casing). For example using values of: • ClassMethodCase of lower_case • ClassMethodPrefix of pre_ • ClassMethodSuffix of _post Identifies and/or transforms class method names as follows: Before: class FOO { public: int CLASS_MEMBER(); }; After: class FOO { public: int pre_class_member_post(); }; ConceptCase When defined, the check will ensure concept names conform to the selected casing. ConceptPrefix When defined, the check will ensure concept names will add the prefixed with the given value (regardless of casing). ConceptIgnoredRegexp Identifier naming checks won't be enforced for concept names matching this regular expression. ConceptSuffix When defined, the check will ensure concept names will add the suffix with the given value (regardless of casing). For example using values of: • ConceptCase of CamelCase • ConceptPrefix of Pre • ConceptSuffix of Post Identifies and/or transforms concept names as follows: Before: template<typename T> concept my_concept = requires (T t) { {t++}; }; After: template<typename T> concept PreMyConceptPost = requires (T t) { {t++}; }; ConstantCase When defined, the check will ensure constant names conform to the selected casing. ConstantPrefix When defined, the check will ensure constant names will add the prefixed with the given value (regardless of casing). ConstantIgnoredRegexp Identifier naming checks won't be enforced for constant names matching this regular expression. ConstantSuffix When defined, the check will ensure constant names will add the suffix with the given value (regardless of casing). ConstantHungarianPrefix When enabled, the check ensures that the declared identifier will have a Hungarian notation prefix based on the declared type. For example using values of: • ConstantCase of lower_case • ConstantPrefix of pre_ • ConstantSuffix of _post • ConstantHungarianPrefix of On Identifies and/or transforms constant names as follows: Before: void function() { unsigned const MyConst_array[] = {1, 2, 3}; } After: void function() { unsigned const pre_myconst_array_post[] = {1, 2, 3}; } ConstantMemberCase When defined, the check will ensure constant member names con- form to the selected casing. ConstantMemberPrefix When defined, the check will ensure constant member names will add the prefixed with the given value (regardless of casing). ConstantMemberIgnoredRegexp Identifier naming checks won't be enforced for constant member names matching this regular expression. ConstantMemberSuffix When defined, the check will ensure constant member names will add the suffix with the given value (regardless of casing). ConstantMemberHungarianPrefix When enabled, the check ensures that the declared identifier will have a Hungarian notation prefix based on the declared type. For example using values of: • ConstantMemberCase of lower_case • ConstantMemberPrefix of pre_ • ConstantMemberSuffix of _post • ConstantMemberHungarianPrefix of On Identifies and/or transforms constant member names as follows: Before: class Foo { char const MY_ConstMember_string[4] = "123"; } After: class Foo { char const pre_my_constmember_string_post[4] = "123"; } ConstantParameterCase When defined, the check will ensure constant parameter names conform to the selected casing. ConstantParameterPrefix When defined, the check will ensure constant parameter names will add the prefixed with the given value (regardless of cas- ing). ConstantParameterIgnoredRegexp Identifier naming checks won't be enforced for constant parame- ter names matching this regular expression. ConstantParameterSuffix When defined, the check will ensure constant parameter names will add the suffix with the given value (regardless of casing). ConstantParameterHungarianPrefix When enabled, the check ensures that the declared identifier will have a Hungarian notation prefix based on the declared type. For example using values of: • ConstantParameterCase of lower_case • ConstantParameterPrefix of pre_ • ConstantParameterSuffix of _post • ConstantParameterHungarianPrefix of On Identifies and/or transforms constant parameter names as follows: Before: void GLOBAL_FUNCTION(int PARAMETER_1, int const CONST_parameter); After: void GLOBAL_FUNCTION(int PARAMETER_1, int const pre_const_parameter_post); ConstantPointerParameterCase When defined, the check will ensure constant pointer parameter names conform to the selected casing. ConstantPointerParameterPrefix When defined, the check will ensure constant pointer parameter names will add the prefixed with the given value (regardless of casing). ConstantPointerParameterIgnoredRegexp Identifier naming checks won't be enforced for constant pointer parameter names matching this regular expression. ConstantPointerParameterSuffix When defined, the check will ensure constant pointer parameter names will add the suffix with the given value (regardless of casing). ConstantPointerParameterHungarianPrefix When enabled, the check ensures that the declared identifier will have a Hungarian notation prefix based on the declared type. For example using values of: • ConstantPointerParameterCase of lower_case • ConstantPointerParameterPrefix of pre_ • ConstantPointerParameterSuffix of _post • ConstantPointerParameterHungarianPrefix of On Identifies and/or transforms constant pointer parameter names as fol- lows: Before: void GLOBAL_FUNCTION(int const *CONST_parameter); After: void GLOBAL_FUNCTION(int const *pre_const_parameter_post); ConstexprFunctionCase When defined, the check will ensure constexpr function names conform to the selected casing. ConstexprFunctionPrefix When defined, the check will ensure constexpr function names will add the prefixed with the given value (regardless of cas- ing). ConstexprFunctionIgnoredRegexp Identifier naming checks won't be enforced for constexpr func- tion names matching this regular expression. ConstexprFunctionSuffix When defined, the check will ensure constexpr function names will add the suffix with the given value (regardless of casing). For example using values of: • ConstexprFunctionCase of lower_case • ConstexprFunctionPrefix of pre_ • ConstexprFunctionSuffix of _post Identifies and/or transforms constexpr function names as follows: Before: constexpr int CE_function() { return 3; } After: constexpr int pre_ce_function_post() { return 3; } ConstexprMethodCase When defined, the check will ensure constexpr method names con- form to the selected casing. ConstexprMethodPrefix When defined, the check will ensure constexpr method names will add the prefixed with the given value (regardless of casing). ConstexprMethodIgnoredRegexp Identifier naming checks won't be enforced for constexpr method names matching this regular expression. ConstexprMethodSuffix When defined, the check will ensure constexpr method names will add the suffix with the given value (regardless of casing). For example using values of: • ConstexprMethodCase of lower_case • ConstexprMethodPrefix of pre_ • ConstexprMethodSuffix of _post Identifies and/or transforms constexpr method names as follows: Before: class Foo { public: constexpr int CST_expr_Method() { return 2; } } After: class Foo { public: constexpr int pre_cst_expr_method_post() { return 2; } } ConstexprVariableCase When defined, the check will ensure constexpr variable names conform to the selected casing. ConstexprVariablePrefix When defined, the check will ensure constexpr variable names will add the prefixed with the given value (regardless of cas- ing). ConstexprVariableIgnoredRegexp Identifier naming checks won't be enforced for constexpr vari- able names matching this regular expression. ConstexprVariableSuffix When defined, the check will ensure constexpr variable names will add the suffix with the given value (regardless of casing). ConstexprVariableHungarianPrefix When enabled, the check ensures that the declared identifier will have a Hungarian notation prefix based on the declared type. For example using values of: • ConstexprVariableCase of lower_case • ConstexprVariablePrefix of pre_ • ConstexprVariableSuffix of _post • ConstexprVariableHungarianPrefix of On Identifies and/or transforms constexpr variable names as follows: Before: constexpr int ConstExpr_variable = MyConstant; After: constexpr int pre_constexpr_variable_post = MyConstant; EnumCase When defined, the check will ensure enumeration names conform to the selected casing. EnumPrefix When defined, the check will ensure enumeration names will add the prefixed with the given value (regardless of casing). EnumIgnoredRegexp Identifier naming checks won't be enforced for enumeration names matching this regular expression. EnumSuffix When defined, the check will ensure enumeration names will add the suffix with the given value (regardless of casing). For example using values of: • EnumCase of lower_case • EnumPrefix of pre_ • EnumSuffix of _post Identifies and/or transforms enumeration names as follows: Before: enum FOO { One, Two, Three }; After: enum pre_foo_post { One, Two, Three }; EnumConstantCase When defined, the check will ensure enumeration constant names conform to the selected casing. EnumConstantPrefix When defined, the check will ensure enumeration constant names will add the prefixed with the given value (regardless of cas- ing). EnumConstantIgnoredRegexp Identifier naming checks won't be enforced for enumeration con- stant names matching this regular expression. EnumConstantSuffix When defined, the check will ensure enumeration constant names will add the suffix with the given value (regardless of casing). EnumConstantHungarianPrefix When enabled, the check ensures that the declared identifier will have a Hungarian notation prefix based on the declared type. For example using values of: • EnumConstantCase of lower_case • EnumConstantPrefix of pre_ • EnumConstantSuffix of _post • EnumConstantHungarianPrefix of On Identifies and/or transforms enumeration constant names as follows: Before: enum FOO { One, Two, Three }; After: enum FOO { pre_One_post, pre_Two_post, pre_Three_post }; FunctionCase When defined, the check will ensure function names conform to the selected casing. FunctionPrefix When defined, the check will ensure function names will add the prefixed with the given value (regardless of casing). FunctionIgnoredRegexp Identifier naming checks won't be enforced for function names matching this regular expression. FunctionSuffix When defined, the check will ensure function names will add the suffix with the given value (regardless of casing). For example using values of: • FunctionCase of lower_case • FunctionPrefix of pre_ • FunctionSuffix of _post Identifies and/or transforms function names as follows: Before: char MY_Function_string(); After: char pre_my_function_string_post(); GetConfigPerFile When true the check will look for the configuration for where an identifier is declared. Useful for when included header files use a different style. Default value is true. GlobalConstantCase When defined, the check will ensure global constant names con- form to the selected casing. GlobalConstantPrefix When defined, the check will ensure global constant names will add the prefixed with the given value (regardless of casing). GlobalConstantIgnoredRegexp Identifier naming checks won't be enforced for global constant names matching this regular expression. GlobalConstantSuffix When defined, the check will ensure global constant names will add the suffix with the given value (regardless of casing). GlobalConstantHungarianPrefix When enabled, the check ensures that the declared identifier will have a Hungarian notation prefix based on the declared type. For example using values of: • GlobalConstantCase of lower_case • GlobalConstantPrefix of pre_ • GlobalConstantSuffix of _post • GlobalConstantHungarianPrefix of On Identifies and/or transforms global constant names as follows: Before: unsigned const MyConstGlobal_array[] = {1, 2, 3}; After: unsigned const pre_myconstglobal_array_post[] = {1, 2, 3}; GlobalConstantPointerCase When defined, the check will ensure global constant pointer names conform to the selected casing. GlobalConstantPointerPrefix When defined, the check will ensure global constant pointer names will add the prefixed with the given value (regardless of casing). GlobalConstantPointerIgnoredRegexp Identifier naming checks won't be enforced for global constant pointer names matching this regular expression. GlobalConstantPointerSuffix When defined, the check will ensure global constant pointer names will add the suffix with the given value (regardless of casing). GlobalConstantPointerHungarianPrefix When enabled, the check ensures that the declared identifier will have a Hungarian notation prefix based on the declared type. For example using values of: • GlobalConstantPointerCase of lower_case • GlobalConstantPointerPrefix of pre_ • GlobalConstantPointerSuffix of _post • GlobalConstantPointerHungarianPrefix of On Identifies and/or transforms global constant pointer names as follows: Before: int *const MyConstantGlobalPointer = nullptr; After: int *const pre_myconstantglobalpointer_post = nullptr; GlobalFunctionCase When defined, the check will ensure global function names con- form to the selected casing. GlobalFunctionPrefix When defined, the check will ensure global function names will add the prefixed with the given value (regardless of casing). GlobalFunctionIgnoredRegexp Identifier naming checks won't be enforced for global function names matching this regular expression. GlobalFunctionSuffix When defined, the check will ensure global function names will add the suffix with the given value (regardless of casing). For example using values of: • GlobalFunctionCase of lower_case • GlobalFunctionPrefix of pre_ • GlobalFunctionSuffix of _post Identifies and/or transforms global function names as follows: Before: void GLOBAL_FUNCTION(int PARAMETER_1, int const CONST_parameter); After: void pre_global_function_post(int PARAMETER_1, int const CONST_parameter); GlobalPointerCase When defined, the check will ensure global pointer names conform to the selected casing. GlobalPointerPrefix When defined, the check will ensure global pointer names will add the prefixed with the given value (regardless of casing). GlobalPointerIgnoredRegexp Identifier naming checks won't be enforced for global pointer names matching this regular expression. GlobalPointerSuffix When defined, the check will ensure global pointer names will add the suffix with the given value (regardless of casing). GlobalPointerHungarianPrefix When enabled, the check ensures that the declared identifier will have a Hungarian notation prefix based on the declared type. For example using values of: • GlobalPointerCase of lower_case • GlobalPointerPrefix of pre_ • GlobalPointerSuffix of _post • GlobalPointerHungarianPrefix of On Identifies and/or transforms global pointer names as follows: Before: int *GLOBAL3; After: int *pre_global3_post; GlobalVariableCase When defined, the check will ensure global variable names con- form to the selected casing. GlobalVariablePrefix When defined, the check will ensure global variable names will add the prefixed with the given value (regardless of casing). GlobalVariableIgnoredRegexp Identifier naming checks won't be enforced for global variable names matching this regular expression. GlobalVariableSuffix When defined, the check will ensure global variable names will add the suffix with the given value (regardless of casing). GlobalVariableHungarianPrefix When enabled, the check ensures that the declared identifier will have a Hungarian notation prefix based on the declared type. For example using values of: • GlobalVariableCase of lower_case • GlobalVariablePrefix of pre_ • GlobalVariableSuffix of _post • GlobalVariableHungarianPrefix of On Identifies and/or transforms global variable names as follows: Before: int GLOBAL3; After: int pre_global3_post; IgnoreMainLikeFunctions When set to true functions that have a similar signature to main or wmain won't enforce checks on the names of their parameters. Default value is false. InlineNamespaceCase When defined, the check will ensure inline namespaces names con- form to the selected casing. InlineNamespacePrefix When defined, the check will ensure inline namespaces names will add the prefixed with the given value (regardless of casing). InlineNamespaceIgnoredRegexp Identifier naming checks won't be enforced for inline namespaces names matching this regular expression. InlineNamespaceSuffix When defined, the check will ensure inline namespaces names will add the suffix with the given value (regardless of casing). For example using values of: • InlineNamespaceCase of lower_case • InlineNamespacePrefix of pre_ • InlineNamespaceSuffix of _post Identifies and/or transforms inline namespaces names as follows: Before: namespace FOO_NS { inline namespace InlineNamespace { ... } } // namespace FOO_NS After: namespace FOO_NS { inline namespace pre_inlinenamespace_post { ... } } // namespace FOO_NS LocalConstantCase When defined, the check will ensure local constant names conform to the selected casing. LocalConstantPrefix When defined, the check will ensure local constant names will add the prefixed with the given value (regardless of casing). LocalConstantIgnoredRegexp Identifier naming checks won't be enforced for local constant names matching this regular expression. LocalConstantSuffix When defined, the check will ensure local constant names will add the suffix with the given value (regardless of casing). LocalConstantHungarianPrefix When enabled, the check ensures that the declared identifier will have a Hungarian notation prefix based on the declared type. For example using values of: • LocalConstantCase of lower_case • LocalConstantPrefix of pre_ • LocalConstantSuffix of _post • LocalConstantHungarianPrefix of On Identifies and/or transforms local constant names as follows: Before: void foo() { int const local_Constant = 3; } After: void foo() { int const pre_local_constant_post = 3; } LocalConstantPointerCase When defined, the check will ensure local constant pointer names conform to the selected casing. LocalConstantPointerPrefix When defined, the check will ensure local constant pointer names will add the prefixed with the given value (regardless of cas- ing). LocalConstantPointerIgnoredRegexp Identifier naming checks won't be enforced for local constant pointer names matching this regular expression. LocalConstantPointerSuffix When defined, the check will ensure local constant pointer names will add the suffix with the given value (regardless of casing). LocalConstantPointerHungarianPrefix When enabled, the check ensures that the declared identifier will have a Hungarian notation prefix based on the declared type. For example using values of: • LocalConstantPointerCase of lower_case • LocalConstantPointerPrefix of pre_ • LocalConstantPointerSuffix of _post • LocalConstantPointerHungarianPrefix of On Identifies and/or transforms local constant pointer names as follows: Before: void foo() { int const *local_Constant = 3; } After: void foo() { int const *pre_local_constant_post = 3; } LocalPointerCase When defined, the check will ensure local pointer names conform to the selected casing. LocalPointerPrefix When defined, the check will ensure local pointer names will add the prefixed with the given value (regardless of casing). LocalPointerIgnoredRegexp Identifier naming checks won't be enforced for local pointer names matching this regular expression. LocalPointerSuffix When defined, the check will ensure local pointer names will add the suffix with the given value (regardless of casing). LocalPointerHungarianPrefix When enabled, the check ensures that the declared identifier will have a Hungarian notation prefix based on the declared type. For example using values of: • LocalPointerCase of lower_case • LocalPointerPrefix of pre_ • LocalPointerSuffix of _post • LocalPointerHungarianPrefix of On Identifies and/or transforms local pointer names as follows: Before: void foo() { int *local_Constant; } After: void foo() { int *pre_local_constant_post; } LocalVariableCase When defined, the check will ensure local variable names conform to the selected casing. LocalVariablePrefix When defined, the check will ensure local variable names will add the prefixed with the given value (regardless of casing). LocalVariableIgnoredRegexp Identifier naming checks won't be enforced for local variable names matching this regular expression. For example using values of: • LocalVariableCase of CamelCase • LocalVariableIgnoredRegexp of \w{1,2} Will exclude variables with a length less than or equal to 2 from the camel case check applied to other variables. LocalVariableSuffix When defined, the check will ensure local variable names will add the suffix with the given value (regardless of casing). LocalVariableHungarianPrefix When enabled, the check ensures that the declared identifier will have a Hungarian notation prefix based on the declared type. For example using values of: • LocalVariableCase of lower_case • LocalVariablePrefix of pre_ • LocalVariableSuffix of _post • LocalVariableHungarianPrefix of On Identifies and/or transforms local variable names as follows: Before: void foo() { int local_Constant; } After: void foo() { int pre_local_constant_post; } MacroDefinitionCase When defined, the check will ensure macro definitions conform to the selected casing. MacroDefinitionPrefix When defined, the check will ensure macro definitions will add the prefixed with the given value (regardless of casing). MacroDefinitionIgnoredRegexp Identifier naming checks won't be enforced for macro definitions matching this regular expression. MacroDefinitionSuffix When defined, the check will ensure macro definitions will add the suffix with the given value (regardless of casing). For example using values of: • MacroDefinitionCase of lower_case • MacroDefinitionPrefix of pre_ • MacroDefinitionSuffix of _post Identifies and/or transforms macro definitions as follows: Before: #define MY_MacroDefinition After: #define pre_my_macro_definition_post Note: This will not warn on builtin macros or macros defined on the command line using the -D flag. MemberCase When defined, the check will ensure member names conform to the selected casing. MemberPrefix When defined, the check will ensure member names will add the prefixed with the given value (regardless of casing). MemberIgnoredRegexp Identifier naming checks won't be enforced for member names matching this regular expression. MemberSuffix When defined, the check will ensure member names will add the suffix with the given value (regardless of casing). MemberHungarianPrefix When enabled, the check ensures that the declared identifier will have a Hungarian notation prefix based on the declared type. For example using values of: • MemberCase of lower_case • MemberPrefix of pre_ • MemberSuffix of _post • MemberHungarianPrefix of On Identifies and/or transforms member names as follows: Before: class Foo { char MY_ConstMember_string[4]; } After: class Foo { char pre_my_constmember_string_post[4]; } MethodCase When defined, the check will ensure method names conform to the selected casing. MethodPrefix When defined, the check will ensure method names will add the prefixed with the given value (regardless of casing). MethodIgnoredRegexp Identifier naming checks won't be enforced for method names matching this regular expression. MethodSuffix When defined, the check will ensure method names will add the suffix with the given value (regardless of casing). For example using values of: • MethodCase of lower_case • MethodPrefix of pre_ • MethodSuffix of _post Identifies and/or transforms method names as follows: Before: class Foo { char MY_Method_string(); } After: class Foo { char pre_my_method_string_post(); } NamespaceCase When defined, the check will ensure namespace names conform to the selected casing. NamespacePrefix When defined, the check will ensure namespace names will add the prefixed with the given value (regardless of casing). NamespaceIgnoredRegexp Identifier naming checks won't be enforced for namespace names matching this regular expression. NamespaceSuffix When defined, the check will ensure namespace names will add the suffix with the given value (regardless of casing). For example using values of: • NamespaceCase of lower_case • NamespacePrefix of pre_ • NamespaceSuffix of _post Identifies and/or transforms namespace names as follows: Before: namespace FOO_NS { ... } After: namespace pre_foo_ns_post { ... } ParameterCase When defined, the check will ensure parameter names conform to the selected casing. ParameterPrefix When defined, the check will ensure parameter names will add the prefixed with the given value (regardless of casing). ParameterIgnoredRegexp Identifier naming checks won't be enforced for parameter names matching this regular expression. ParameterSuffix When defined, the check will ensure parameter names will add the suffix with the given value (regardless of casing). ParameterHungarianPrefix When enabled, the check ensures that the declared identifier will have a Hungarian notation prefix based on the declared type. For example using values of: • ParameterCase of lower_case • ParameterPrefix of pre_ • ParameterSuffix of _post • ParameterHungarianPrefix of On Identifies and/or transforms parameter names as follows: Before: void GLOBAL_FUNCTION(int PARAMETER_1, int const CONST_parameter); After: void GLOBAL_FUNCTION(int pre_parameter_post, int const CONST_parameter); ParameterPackCase When defined, the check will ensure parameter pack names conform to the selected casing. ParameterPackPrefix When defined, the check will ensure parameter pack names will add the prefixed with the given value (regardless of casing). ParameterPackIgnoredRegexp Identifier naming checks won't be enforced for parameter pack names matching this regular expression. ParameterPackSuffix When defined, the check will ensure parameter pack names will add the suffix with the given value (regardless of casing). For example using values of: • ParameterPackCase of lower_case • ParameterPackPrefix of pre_ • ParameterPackSuffix of _post Identifies and/or transforms parameter pack names as follows: Before: template <typename... TYPE_parameters> { void FUNCTION(int... TYPE_parameters); } After: template <typename... TYPE_parameters> { void FUNCTION(int... pre_type_parameters_post); } PointerParameterCase When defined, the check will ensure pointer parameter names con- form to the selected casing. PointerParameterPrefix When defined, the check will ensure pointer parameter names will add the prefixed with the given value (regardless of casing). PointerParameterIgnoredRegexp Identifier naming checks won't be enforced for pointer parameter names matching this regular expression. PointerParameterSuffix When defined, the check will ensure pointer parameter names will add the suffix with the given value (regardless of casing). PointerParameterHungarianPrefix When enabled, the check ensures that the declared identifier will have a Hungarian notation prefix based on the declared type. For example using values of: • PointerParameterCase of lower_case • PointerParameterPrefix of pre_ • PointerParameterSuffix of _post • PointerParameterHungarianPrefix of On Identifies and/or transforms pointer parameter names as follows: Before: void FUNCTION(int *PARAMETER); After: void FUNCTION(int *pre_parameter_post); PrivateMemberCase When defined, the check will ensure private member names conform to the selected casing. PrivateMemberPrefix When defined, the check will ensure private member names will add the prefixed with the given value (regardless of casing). PrivateMemberIgnoredRegexp Identifier naming checks won't be enforced for private member names matching this regular expression. PrivateMemberSuffix When defined, the check will ensure private member names will add the suffix with the given value (regardless of casing). PrivateMemberHungarianPrefix When enabled, the check ensures that the declared identifier will have a Hungarian notation prefix based on the declared type. For example using values of: • PrivateMemberCase of lower_case • PrivateMemberPrefix of pre_ • PrivateMemberSuffix of _post • PrivateMemberHungarianPrefix of On Identifies and/or transforms private member names as follows: Before: class Foo { private: int Member_Variable; } After: class Foo { private: int pre_member_variable_post; } PrivateMethodCase When defined, the check will ensure private method names conform to the selected casing. PrivateMethodPrefix When defined, the check will ensure private method names will add the prefixed with the given value (regardless of casing). PrivateMethodIgnoredRegexp Identifier naming checks won't be enforced for private method names matching this regular expression. PrivateMethodSuffix When defined, the check will ensure private method names will add the suffix with the given value (regardless of casing). For example using values of: • PrivateMethodCase of lower_case • PrivateMethodPrefix of pre_ • PrivateMethodSuffix of _post Identifies and/or transforms private method names as follows: Before: class Foo { private: int Member_Method(); } After: class Foo { private: int pre_member_method_post(); } ProtectedMemberCase When defined, the check will ensure protected member names con- form to the selected casing. ProtectedMemberPrefix When defined, the check will ensure protected member names will add the prefixed with the given value (regardless of casing). ProtectedMemberIgnoredRegexp Identifier naming checks won't be enforced for protected member names matching this regular expression. ProtectedMemberSuffix When defined, the check will ensure protected member names will add the suffix with the given value (regardless of casing). ProtectedMemberHungarianPrefix When enabled, the check ensures that the declared identifier will have a Hungarian notation prefix based on the declared type. For example using values of: • ProtectedMemberCase of lower_case • ProtectedMemberPrefix of pre_ • ProtectedMemberSuffix of _post • ProtectedMemberHungarianPrefix of On Identifies and/or transforms protected member names as follows: Before: class Foo { protected: int Member_Variable; } After: class Foo { protected: int pre_member_variable_post; } ProtectedMethodCase When defined, the check will ensure protected method names con- form to the selected casing. ProtectedMethodPrefix When defined, the check will ensure protected method names will add the prefixed with the given value (regardless of casing). ProtectedMethodIgnoredRegexp Identifier naming checks won't be enforced for protected method names matching this regular expression. ProtectedMethodSuffix When defined, the check will ensure protected method names will add the suffix with the given value (regardless of casing). For example using values of: • ProtectedMethodCase of lower_case • ProtectedMethodPrefix of pre_ • ProtectedMethodSuffix of _post Identifies and/or transforms protect method names as follows: Before: class Foo { protected: int Member_Method(); } After: class Foo { protected: int pre_member_method_post(); } PublicMemberCase When defined, the check will ensure public member names conform to the selected casing. PublicMemberPrefix When defined, the check will ensure public member names will add the prefixed with the given value (regardless of casing). PublicMemberIgnoredRegexp Identifier naming checks won't be enforced for public member names matching this regular expression. PublicMemberSuffix When defined, the check will ensure public member names will add the suffix with the given value (regardless of casing). PublicMemberHungarianPrefix When enabled, the check ensures that the declared identifier will have a Hungarian notation prefix based on the declared type. For example using values of: • PublicMemberCase of lower_case • PublicMemberPrefix of pre_ • PublicMemberSuffix of _post • PublicMemberHungarianPrefix of On Identifies and/or transforms public member names as follows: Before: class Foo { public: int Member_Variable; } After: class Foo { public: int pre_member_variable_post; } PublicMethodCase When defined, the check will ensure public method names conform to the selected casing. PublicMethodPrefix When defined, the check will ensure public method names will add the prefixed with the given value (regardless of casing). PublicMethodIgnoredRegexp Identifier naming checks won't be enforced for public method names matching this regular expression. PublicMethodSuffix When defined, the check will ensure public method names will add the suffix with the given value (regardless of casing). For example using values of: • PublicMethodCase of lower_case • PublicMethodPrefix of pre_ • PublicMethodSuffix of _post Identifies and/or transforms public method names as follows: Before: class Foo { public: int Member_Method(); } After: class Foo { public: int pre_member_method_post(); } ScopedEnumConstantCase When defined, the check will ensure scoped enum constant names conform to the selected casing. ScopedEnumConstantPrefix When defined, the check will ensure scoped enum constant names will add the prefixed with the given value (regardless of cas- ing). ScopedEnumConstantIgnoredRegexp Identifier naming checks won't be enforced for scoped enum con- stant names matching this regular expression. ScopedEnumConstantSuffix When defined, the check will ensure scoped enum constant names will add the suffix with the given value (regardless of casing). ScopedEnumConstantHungarianPrefix When enabled, the check ensures that the declared identifier will have a Hungarian notation prefix based on the declared type. For example using values of: • ScopedEnumConstantCase of lower_case • ScopedEnumConstantPrefix of pre_ • ScopedEnumConstantSuffix of _post • ScopedEnumConstantHungarianPrefix of On Identifies and/or transforms enumeration constant names as follows: Before: enum class FOO { One, Two, Three }; After: enum class FOO { pre_One_post, pre_Two_post, pre_Three_post }; StaticConstantCase When defined, the check will ensure static constant names con- form to the selected casing. StaticConstantPrefix When defined, the check will ensure static constant names will add the prefixed with the given value (regardless of casing). StaticConstantIgnoredRegexp Identifier naming checks won't be enforced for static constant names matching this regular expression. StaticConstantSuffix When defined, the check will ensure static constant names will add the suffix with the given value (regardless of casing). StaticConstantHungarianPrefix When enabled, the check ensures that the declared identifier will have a Hungarian notation prefix based on the declared type. For example using values of: • StaticConstantCase of lower_case • StaticConstantPrefix of pre_ • StaticConstantSuffix of _post • StaticConstantHungarianPrefix of On Identifies and/or transforms static constant names as follows: Before: static unsigned const MyConstStatic_array[] = {1, 2, 3}; After: static unsigned const pre_myconststatic_array_post[] = {1, 2, 3}; StaticVariableCase When defined, the check will ensure static variable names con- form to the selected casing. StaticVariablePrefix When defined, the check will ensure static variable names will add the prefixed with the given value (regardless of casing). StaticVariableIgnoredRegexp Identifier naming checks won't be enforced for static variable names matching this regular expression. StaticVariableSuffix When defined, the check will ensure static variable names will add the suffix with the given value (regardless of casing). StaticVariableHungarianPrefix When enabled, the check ensures that the declared identifier will have a Hungarian notation prefix based on the declared type. For example using values of: • StaticVariableCase of lower_case • StaticVariablePrefix of pre_ • StaticVariableSuffix of _post • StaticVariableHungarianPrefix of On Identifies and/or transforms static variable names as follows: Before: static unsigned MyStatic_array[] = {1, 2, 3}; After: static unsigned pre_mystatic_array_post[] = {1, 2, 3}; StructCase When defined, the check will ensure struct names conform to the selected casing. StructPrefix When defined, the check will ensure struct names will add the prefixed with the given value (regardless of casing). StructIgnoredRegexp Identifier naming checks won't be enforced for struct names matching this regular expression. StructSuffix When defined, the check will ensure struct names will add the suffix with the given value (regardless of casing). For example using values of: • StructCase of lower_case • StructPrefix of pre_ • StructSuffix of _post Identifies and/or transforms struct names as follows: Before: struct FOO { FOO(); ~FOO(); }; After: struct pre_foo_post { pre_foo_post(); ~pre_foo_post(); }; TemplateParameterCase When defined, the check will ensure template parameter names conform to the selected casing. TemplateParameterPrefix When defined, the check will ensure template parameter names will add the prefixed with the given value (regardless of cas- ing). TemplateParameterIgnoredRegexp Identifier naming checks won't be enforced for template parame- ter names matching this regular expression. TemplateParameterSuffix When defined, the check will ensure template parameter names will add the suffix with the given value (regardless of casing). For example using values of: • TemplateParameterCase of lower_case • TemplateParameterPrefix of pre_ • TemplateParameterSuffix of _post Identifies and/or transforms template parameter names as follows: Before: template <typename T> class Foo {}; After: template <typename pre_t_post> class Foo {}; TemplateTemplateParameterCase When defined, the check will ensure template template parameter names conform to the selected casing. TemplateTemplateParameterPrefix When defined, the check will ensure template template parameter names will add the prefixed with the given value (regardless of casing). TemplateTemplateParameterIgnoredRegexp Identifier naming checks won't be enforced for template template parameter names matching this regular expression. TemplateTemplateParameterSuffix When defined, the check will ensure template template parameter names will add the suffix with the given value (regardless of casing). For example using values of: • TemplateTemplateParameterCase of lower_case • TemplateTemplateParameterPrefix of pre_ • TemplateTemplateParameterSuffix of _post Identifies and/or transforms template template parameter names as fol- lows: Before: template <template <typename> class TPL_parameter, int COUNT_params, typename... TYPE_parameters> After: template <template <typename> class pre_tpl_parameter_post, int COUNT_params, typename... TYPE_parameters> TypeAliasCase When defined, the check will ensure type alias names conform to the selected casing. TypeAliasPrefix When defined, the check will ensure type alias names will add the prefixed with the given value (regardless of casing). TypeAliasIgnoredRegexp Identifier naming checks won't be enforced for type alias names matching this regular expression. TypeAliasSuffix When defined, the check will ensure type alias names will add the suffix with the given value (regardless of casing). For example using values of: • TypeAliasCase of lower_case • TypeAliasPrefix of pre_ • TypeAliasSuffix of _post Identifies and/or transforms type alias names as follows: Before: using MY_STRUCT_TYPE = my_structure; After: using pre_my_struct_type_post = my_structure; TypedefCase When defined, the check will ensure typedef names conform to the selected casing. TypedefPrefix When defined, the check will ensure typedef names will add the prefixed with the given value (regardless of casing). TypedefIgnoredRegexp Identifier naming checks won't be enforced for typedef names matching this regular expression. TypedefSuffix When defined, the check will ensure typedef names will add the suffix with the given value (regardless of casing). For example using values of: • TypedefCase of lower_case • TypedefPrefix of pre_ • TypedefSuffix of _post Identifies and/or transforms typedef names as follows: Before: typedef int MYINT; After: typedef int pre_myint_post; TypeTemplateParameterCase When defined, the check will ensure type template parameter names conform to the selected casing. TypeTemplateParameterPrefix When defined, the check will ensure type template parameter names will add the prefixed with the given value (regardless of casing). TypeTemplateParameterIgnoredRegexp Identifier naming checks won't be enforced for type template names matching this regular expression. TypeTemplateParameterSuffix When defined, the check will ensure type template parameter names will add the suffix with the given value (regardless of casing). For example using values of: • TypeTemplateParameterCase of lower_case • TypeTemplateParameterPrefix of pre_ • TypeTemplateParameterSuffix of _post Identifies and/or transforms type template parameter names as follows: Before: template <template <typename> class TPL_parameter, int COUNT_params, typename... TYPE_parameters> After: template <template <typename> class TPL_parameter, int COUNT_params, typename... pre_type_parameters_post> UnionCase When defined, the check will ensure union names conform to the selected casing. UnionPrefix When defined, the check will ensure union names will add the prefixed with the given value (regardless of casing). UnionIgnoredRegexp Identifier naming checks won't be enforced for union names matching this regular expression. UnionSuffix When defined, the check will ensure union names will add the suffix with the given value (regardless of casing). For example using values of: • UnionCase of lower_case • UnionPrefix of pre_ • UnionSuffix of _post Identifies and/or transforms union names as follows: Before: union FOO { int a; char b; }; After: union pre_foo_post { int a; char b; }; ValueTemplateParameterCase When defined, the check will ensure value template parameter names conform to the selected casing. ValueTemplateParameterPrefix When defined, the check will ensure value template parameter names will add the prefixed with the given value (regardless of casing). ValueTemplateParameterIgnoredRegexp Identifier naming checks won't be enforced for value template parameter names matching this regular expression. ValueTemplateParameterSuffix When defined, the check will ensure value template parameter names will add the suffix with the given value (regardless of casing). For example using values of: • ValueTemplateParameterCase of lower_case • ValueTemplateParameterPrefix of pre_ • ValueTemplateParameterSuffix of _post Identifies and/or transforms value template parameter names as follows: Before: template <template <typename> class TPL_parameter, int COUNT_params, typename... TYPE_parameters> After: template <template <typename> class TPL_parameter, int pre_count_params_post, typename... TYPE_parameters> VariableCase When defined, the check will ensure variable names conform to the selected casing. VariablePrefix When defined, the check will ensure variable names will add the prefixed with the given value (regardless of casing). VariableIgnoredRegexp Identifier naming checks won't be enforced for variable names matching this regular expression. VariableSuffix When defined, the check will ensure variable names will add the suffix with the given value (regardless of casing). VariableHungarianPrefix When enabled, the check ensures that the declared identifier will have a Hungarian notation prefix based on the declared type. For example using values of: • VariableCase of lower_case • VariablePrefix of pre_ • VariableSuffix of _post • VariableHungarianPrefix of On Identifies and/or transforms variable names as follows: Before: unsigned MyVariable; After: unsigned pre_myvariable_post; VirtualMethodCase When defined, the check will ensure virtual method names conform to the selected casing. VirtualMethodPrefix When defined, the check will ensure virtual method names will add the prefixed with the given value (regardless of casing). VirtualMethodIgnoredRegexp Identifier naming checks won't be enforced for virtual method names matching this regular expression. VirtualMethodSuffix When defined, the check will ensure virtual method names will add the suffix with the given value (regardless of casing). For example using values of: • VirtualMethodCase of lower_case • VirtualMethodPrefix of pre_ • VirtualMethodSuffix of _post Identifies and/or transforms virtual method names as follows: Before: class Foo { public: virtual int MemberFunction(); } After: class Foo { public: virtual int pre_member_function_post(); } The default mapping table of Hungarian Notation In Hungarian notation, a variable name starts with a group of lower-case letters which are mnemonics for the type or purpose of that variable, followed by whatever name the programmer has chosen; this last part is sometimes distinguished as the given name. The first char- acter of the given name can be capitalized to separate it from the type indicators (see also CamelCase). Otherwise the case of this character denotes scope. The following table is the default mapping table of Hungarian Notation which maps Decl to its prefix string. You can also have your own style in config file. +-------------+--------+-------------+--------+-----------+--------+ | Primitive | | | | Microsoft | | | Type | | | | Type | | +-------------+--------+-------------+--------+-----------+--------+ | Type | Prefix | Type | Prefix | Type | Prefix | +-------------+--------+-------------+--------+-----------+--------+ | int8_t | i8 | signed int | si | BOOL | b | +-------------+--------+-------------+--------+-----------+--------+ | int16_t | i16 | signed | ss | BOOLEAN | b | | | | short | | | | +-------------+--------+-------------+--------+-----------+--------+ | int32_t | i32 | signed | ssi | BYTE | by | | | | short int | | | | +-------------+--------+-------------+--------+-----------+--------+ | int64_t | i64 | signed long | slli | CHAR | c | | | | long int | | | | +-------------+--------+-------------+--------+-----------+--------+ | uint8_t | u8 | signed long | sll | UCHAR | uc | | | | long | | | | +-------------+--------+-------------+--------+-----------+--------+ | uint16_t | u16 | signed long | sli | SHORT | s | | | | int | | | | +-------------+--------+-------------+--------+-----------+--------+ | uint32_t | u32 | signed long | sl | USHORT | us | +-------------+--------+-------------+--------+-----------+--------+ | uint64_t | u64 | signed | s | WORD | w | +-------------+--------+-------------+--------+-----------+--------+ | char8_t | c8 | unsigned | ulli | DWORD | dw | | | | long long | | | | | | | int | | | | +-------------+--------+-------------+--------+-----------+--------+ | char16_t | c16 | unsigned | ull | DWORD32 | dw32 | | | | long long | | | | +-------------+--------+-------------+--------+-----------+--------+ | char32_t | c32 | unsigned | uli | DWORD64 | dw64 | | | | long int | | | | +-------------+--------+-------------+--------+-----------+--------+ | float | f | unsigned | ul | LONG | l | | | | long | | | | +-------------+--------+-------------+--------+-----------+--------+ | double | d | unsigned | usi | ULONG | ul | | | | short int | | | | +-------------+--------+-------------+--------+-----------+--------+ | char | c | unsigned | us | ULONG32 | ul32 | | | | short | | | | +-------------+--------+-------------+--------+-----------+--------+ | bool | b | unsigned | ui | ULONG64 | ul64 | | | | int | | | | +-------------+--------+-------------+--------+-----------+--------+ | _Bool | b | unsigned | uc | ULONGLONG | ull | | | | char | | | | +-------------+--------+-------------+--------+-----------+--------+ | int | i | unsigned | u | HANDLE | h | +-------------+--------+-------------+--------+-----------+--------+ | size_t | n | long long | lli | INT | i | | | | int | | | | +-------------+--------+-------------+--------+-----------+--------+ | short | s | long double | ld | INT8 | i8 | +-------------+--------+-------------+--------+-----------+--------+ | signed | i | long long | ll | INT16 | i16 | +-------------+--------+-------------+--------+-----------+--------+ | unsigned | u | long int | li | INT32 | i32 | +-------------+--------+-------------+--------+-----------+--------+ | long | l | long | l | INT64 | i64 | +-------------+--------+-------------+--------+-----------+--------+ | long long | ll | ptrdiff_t | p | UINT | ui | +-------------+--------+-------------+--------+-----------+--------+ | unsigned | ul | void | none | UINT8 | u8 | | long | | | | | | +-------------+--------+-------------+--------+-----------+--------+ | long double | ld | | | UINT16 | u16 | +-------------+--------+-------------+--------+-----------+--------+ | ptrdiff_t | p | | | UINT32 | u32 | +-------------+--------+-------------+--------+-----------+--------+ | wchar_t | wc | | | UINT64 | u64 | +-------------+--------+-------------+--------+-----------+--------+ | short int | si | | | PVOID | p | +-------------+--------+-------------+--------+-----------+--------+ | short | s | | | | | +-------------+--------+-------------+--------+-----------+--------+ There are more trivial options for Hungarian Notation: HungarianNotation.General.* Options are not belonging to any specific Decl. HungarianNotation.CString.* Options for NULL-terminated string. HungarianNotation.DerivedType.* Options for derived types. HungarianNotation.PrimitiveType.* Options for primitive types. HungarianNotation.UserDefinedType.* Options for user-defined types. Options for Hungarian Notation • HungarianNotation.General.TreatStructAsClass • HungarianNotation.DerivedType.Array • HungarianNotation.DerivedType.Pointer • HungarianNotation.DerivedType.FunctionPointer • HungarianNotation.CString.CharPointer • HungarianNotation.CString.CharArray • HungarianNotation.CString.WideCharPointer • HungarianNotation.CString.WideCharArray • HungarianNotation.PrimitiveType.* • HungarianNotation.UserDefinedType.* HungarianNotation.General.TreatStructAsClass When defined, the check will treat naming of struct as a class. The default value is false. HungarianNotation.DerivedType.Array When defined, the check will ensure variable name will add the prefix with the given string. The default prefix is a. HungarianNotation.DerivedType.Pointer When defined, the check will ensure variable name will add the prefix with the given string. The default prefix is p. HungarianNotation.DerivedType.FunctionPointer When defined, the check will ensure variable name will add the prefix with the given string. The default prefix is fn. Before: // Array int DataArray[2] = {0}; // Pointer void *DataBuffer = NULL; // FunctionPointer typedef void (*FUNC_PTR)(); FUNC_PTR FuncPtr = NULL; After: // Array int aDataArray[2] = {0}; // Pointer void *pDataBuffer = NULL; // FunctionPointer typedef void (*FUNC_PTR)(); FUNC_PTR fnFuncPtr = NULL; HungarianNotation.CString.CharPointer When defined, the check will ensure variable name will add the prefix with the given string. The default prefix is sz. HungarianNotation.CString.CharArray When defined, the check will ensure variable name will add the prefix with the given string. The default prefix is sz. HungarianNotation.CString.WideCharPointer When defined, the check will ensure variable name will add the prefix with the given string. The default prefix is wsz. HungarianNotation.CString.WideCharArray When defined, the check will ensure variable name will add the prefix with the given string. The default prefix is wsz. Before: // CharPointer const char *NamePtr = "Name"; // CharArray const char NameArray[] = "Name"; // WideCharPointer const wchar_t *WideNamePtr = L"Name"; // WideCharArray const wchar_t WideNameArray[] = L"Name"; After: // CharPointer const char *szNamePtr = "Name"; // CharArray const char szNameArray[] = "Name"; // WideCharPointer const wchar_t *wszWideNamePtr = L"Name"; // WideCharArray const wchar_t wszWideNameArray[] = L"Name"; HungarianNotation.PrimitiveType.* When defined, the check will ensure variable name of involved primitive types will add the prefix with the given string. The default prefixes are defined in the default mapping table. HungarianNotation.UserDefinedType.* When defined, the check will ensure variable name of involved primitive types will add the prefix with the given string. The default prefixes are defined in the default mapping table. Before: int8_t ValueI8 = 0; int16_t ValueI16 = 0; int32_t ValueI32 = 0; int64_t ValueI64 = 0; uint8_t ValueU8 = 0; uint16_t ValueU16 = 0; uint32_t ValueU32 = 0; uint64_t ValueU64 = 0; float ValueFloat = 0.0; double ValueDouble = 0.0; ULONG ValueUlong = 0; DWORD ValueDword = 0; After: int8_t i8ValueI8 = 0; int16_t i16ValueI16 = 0; int32_t i32ValueI32 = 0; int64_t i64ValueI64 = 0; uint8_t u8ValueU8 = 0; uint16_t u16ValueU16 = 0; uint32_t u32ValueU32 = 0; uint64_t u64ValueU64 = 0; float fValueFloat = 0.0; double dValueDouble = 0.0; ULONG ulValueUlong = 0; DWORD dwValueDword = 0; readability-implicit-bool-cast This check has been renamed to readability-implicit-bool-conversion. readability-implicit-bool-conversion This check can be used to find implicit conversions between built-in types and booleans. Depending on use case, it may simply help with readability of the code, or in some cases, point to potential bugs which remain unnoticed due to implicit conversions. The following is a real-world example of bug which was hiding behind implicit bool conversion: class Foo { int m_foo; public: void setFoo(bool foo) { m_foo = foo; } // warning: implicit conversion bool -> int int getFoo() { return m_foo; } }; void use(Foo& foo) { bool value = foo.getFoo(); // warning: implicit conversion int -> bool } This code is the result of unsuccessful refactoring, where type of m_foo changed from bool to int. The programmer forgot to change all oc- currences of bool, and the remaining code is no longer correct, yet it still compiles without any visible warnings. In addition to issuing warnings, fix-it hints are provided to help solve the reported issues. This can be used for improving readability of code, for example: void conversionsToBool() { float floating; bool boolean = floating; // ^ propose replacement: bool boolean = floating != 0.0f; int integer; if (integer) {} // ^ propose replacement: if (integer != 0) {} int* pointer; if (!pointer) {} // ^ propose replacement: if (pointer == nullptr) {} while (1) {} // ^ propose replacement: while (true) {} } void functionTakingInt(int param); void conversionsFromBool() { bool boolean; functionTakingInt(boolean); // ^ propose replacement: functionTakingInt(static_cast<int>(boolean)); functionTakingInt(true); // ^ propose replacement: functionTakingInt(1); } In general, the following conversion types are checked: • integer expression/literal to boolean (conversion from a single bit bitfield to boolean is explicitly allowed, since there's no ambiguity / information loss in this case), • floating expression/literal to boolean, • pointer/pointer to member/nullptr/NULL to boolean, • boolean expression/literal to integer (conversion from boolean to a single bit bitfield is explicitly allowed), • boolean expression/literal to floating. The rules for generating fix-it hints are: • in case of conversions from other built-in type to bool, an explicit comparison is proposed to make it clear what exactly is being com- pared: • bool boolean = floating; is changed to bool boolean = floating == 0.0f;, • for other types, appropriate literals are used (0, 0u, 0.0f, 0.0, nullptr), • in case of negated expressions conversion to bool, the proposed re- placement with comparison is simplified: • if (!pointer) is changed to if (pointer == nullptr), • in case of conversions from bool to other built-in types, an explicit static_cast is proposed to make it clear that a conversion is taking place: • int integer = boolean; is changed to int integer = sta- tic_cast<int>(boolean);, • if the conversion is performed on type literals, an equivalent lit- eral is proposed, according to what type is actually expected, for example: • functionTakingBool(0); is changed to functionTakingBool(false);, • functionTakingInt(true); is changed to functionTakingInt(1);, • for other types, appropriate literals are used (false, true, 0, 1, 0u, 1u, 0.0f, 1.0f, 0.0, 1.0f). Some additional accommodations are made for pre-C++11 dialects: • false literal conversion to pointer is detected, • instead of nullptr literal, 0 is proposed as replacement. Occurrences of implicit conversions inside macros and template instan- tiations are deliberately ignored, as it is not clear how to deal with such cases. Options AllowIntegerConditions When true, the check will allow conditional integer conversions. Default is false. AllowPointerConditions When true, the check will allow conditional pointer conversions. Default is false. readability-inconsistent-declaration-parameter-name Find function declarations which differ in parameter names. Example: // in foo.hpp: void foo(int a, int b, int c); // in foo.cpp: void foo(int d, int e, int f); // warning This check should help to enforce consistency in large projects, where it often happens that a definition of function is refactored, changing the parameter names, but its declaration in header file is not updated. With this check, we can easily find and correct such inconsistencies, keeping declaration and definition always in sync. Unnamed parameters are allowed and are not taken into account when com- paring function declarations, for example: void foo(int a); void foo(int); // no warning One name is also allowed to be a case-insensitive prefix/suffix of the other: void foo(int count); void foo(int count_input) { // no warning int count = adjustCount(count_input); } To help with refactoring, in some cases fix-it hints are generated to align parameter names to a single naming convention. This works with the assumption that the function definition is the most up-to-date ver- sion, as it directly references parameter names in its body. Example: void foo(int a); // warning and fix-it hint (replace "a" to "b") int foo(int b) { return b + 2; } // definition with use of "b" In the case of multiple redeclarations or function template specializa- tions, a warning is issued for every redeclaration or specialization inconsistent with the definition or the first declaration seen in a translation unit. IgnoreMacros If this option is set to true (default is true), the check will not warn about names declared inside macros. Strict If this option is set to true (default is false), then names must match exactly (or be absent). readability-isolate-declaration Detects local variable declarations declaring more than one variable and tries to refactor the code to one statement per declaration. The automatic code-transformation will use the same indentation as the original for every created statement and add a line break after each statement. It keeps the order of the variable declarations consistent, too. void f() { int * pointer = nullptr, value = 42, * const const_ptr = &value; // This declaration will be diagnosed and transformed into: // int * pointer = nullptr; // int value = 42; // int * const const_ptr = &value; } The check excludes places where it is necessary or common to declare multiple variables in one statement and there is no other way supported in the language. Please note that structured bindings are not consid- ered. // It is not possible to transform this declaration and doing the declaration // before the loop will increase the scope of the variable 'Begin' and 'End' // which is undesirable. for (int Begin = 0, End = 100; Begin < End; ++Begin); if (int Begin = 42, Result = some_function(Begin); Begin == Result); // It is not possible to transform this declaration because the result is // not functionality preserving as 'j' and 'k' would not be part of the // 'if' statement anymore. if (SomeCondition()) int i = 42, j = 43, k = function(i,j); Limitations Global variables and member variables are excluded. The check currently does not support the automatic transformation of member-pointer-types. struct S { int a; const int b; void f() {} }; void f() { // Only a diagnostic message is emitted int S::*p = &S::a, S::*const q = &S::a; } Furthermore, the transformation is very cautious when it detects vari- ous kinds of macros or preprocessor directives in the range of the statement. In this case the transformation will not happen to avoid un- expected side-effects due to macros. #define NULL 0 #define MY_NICE_TYPE int ** #define VAR_NAME(name) name##__LINE__ #define A_BUNCH_OF_VARIABLES int m1 = 42, m2 = 43, m3 = 44; void macros() { int *p1 = NULL, *p2 = NULL; // Will be transformed to // int *p1 = NULL; // int *p2 = NULL; MY_NICE_TYPE p3, v1, v2; // Won't be transformed, but a diagnostic is emitted. int VAR_NAME(v3), VAR_NAME(v4), VAR_NAME(v5); // Won't be transformed, but a diagnostic is emitted. A_BUNCH_OF_VARIABLES // Won't be transformed, but a diagnostic is emitted. int Unconditional, #if CONFIGURATION IfConfigured = 42, #else IfConfigured = 0; #endif // Won't be transformed, but a diagnostic is emitted. } readability-magic-numbers Detects magic numbers, integer or floating point literals that are em- bedded in code and not introduced via constants or symbols. Many coding guidelines advise replacing the magic values with symbolic constants to improve readability. Here are a few references: • Rule ES.45: Avoid "magic constants"; use symbolic constants in C++ Core Guidelines • Rule 5.1.1 Use symbolic names instead of literal values in code in High Integrity C++ • Item 17 in "C++ Coding Standards: 101 Rules, Guidelines and Best Practices" by Herb Sutter and Andrei Alexandrescu • Chapter 17 in "Clean Code - A handbook of agile software crafts- manship." by Robert C. Martin • Rule 20701 in "TRAIN REAL TIME DATA PROTOCOL Coding Rules" by Armin-Hagen Weiss, Bombardier • http://wiki.c2.com/?MagicNumber Examples of magic values: template<typename T, size_t N> struct CustomType { T arr[N]; }; struct OtherType { CustomType<int, 30> container; } CustomType<int, 30> values; double circleArea = 3.1415926535 * radius * radius; double totalCharge = 1.08 * itemPrice; int getAnswer() { return -3; // FILENOTFOUND } for (int mm = 1; mm <= 12; ++mm) { std::cout << month[mm] << '\n'; } Example with magic values refactored: template<typename T, size_t N> struct CustomType { T arr[N]; }; const size_t NUMBER_OF_ELEMENTS = 30; using containerType = CustomType<int, NUMBER_OF_ELEMENTS>; struct OtherType { containerType container; } containerType values; double circleArea = M_PI * radius * radius; const double TAX_RATE = 0.08; // or make it variable and read from a file double totalCharge = (1.0 + TAX_RATE) * itemPrice; int getAnswer() { return E_FILE_NOT_FOUND; } for (int mm = 1; mm <= MONTHS_IN_A_YEAR; ++mm) { std::cout << month[mm] << '\n'; } For integral literals by default only 0 and 1 (and -1) integer values are accepted without a warning. This can be overridden with the IgnoredIntegerValues option. Negative values are accepted if their ab- solute value is present in the IgnoredIntegerValues list. As a special case for integral values, all powers of two can be ac- cepted without warning by enabling the IgnorePowersOf2IntegerValues op- tion. For floating point literals by default the 0.0 floating point value is accepted without a warning. The set of ignored floating point literals can be configured using the IgnoredFloatingPointValues option. For each value in that set, the given string value is converted to a float- ing-point value representation used by the target architecture. If a floating-point literal value compares equal to one of the converted values, then that literal is not diagnosed by this check. Because floating-point equality is used to determine whether to diagnose or not, the user needs to be aware of the details of floating-point repre- sentations for any values that cannot be precisely represented for their target architecture. For each value in the IgnoredFloatingPointValues set, both the sin- gle-precision form and double-precision form are accepted (for example, if 3.14 is in the set, neither 3.14f nor 3.14 will produce a warning). Scientific notation is supported for both source code input and option. Alternatively, the check for the floating point numbers can be disabled for all floating point values by enabling the IgnoreAllFloatingPointValues option. Since values 0 and 0.0 are so common as the base counter of loops, or initialization values for sums, they are always accepted without warn- ing, even if not present in the respective ignored values list. Options IgnoredIntegerValues Semicolon-separated list of magic positive integers that will be accepted without a warning. Default values are {1, 2, 3, 4}, and 0 is accepted unconditionally. IgnorePowersOf2IntegerValues Boolean value indicating whether to accept all powers-of-two in- teger values without warning. Default value is false. IgnoredFloatingPointValues Semicolon-separated list of magic positive floating point values that will be accepted without a warning. Default values are {1.0, 100.0} and 0.0 is accepted unconditionally. IgnoreAllFloatingPointValues Boolean value indicating whether to accept all floating point values without warning. Default value is false. IgnoreBitFieldsWidths Boolean value indicating whether to accept magic numbers as bit field widths without warning. This is useful for example for register definitions which are generated from hardware specifi- cations. Default value is true. IgnoreTypeAliases Boolean value indicating whether to accept magic numbers in typedef or using declarations. Default value is false. IgnoreUserDefinedLiterals Boolean value indicating whether to accept magic numbers in user-defined literals. Default value is false. readability-make-member-function-const Finds non-static member functions that can be made const because the functions don't use this in a non-const way. This check tries to annotate methods according to logical constness (not physical constness). Therefore, it will suggest to add a const qualifier to a non-const method only if this method does something that is already possible though the public interface on a const pointer to the object: • reading a public member variable • calling a public const-qualified member function • returning const-qualified this • passing const-qualified this as a parameter. This check will also suggest to add a const qualifier to a non-const method if this method uses private data and functions in a limited num- ber of ways where logical constness and physical constness coincide: • reading a member variable of builtin type Specifically, this check will not suggest to add a const to a non-const method if the method reads a private member variable of pointer type because that allows to modify the pointee which might not preserve log- ical constness. For the same reason, it does not allow to call private member functions or member functions on private member variables. In addition, this check ignores functions that • are declared virtual • contain a const_cast • are templated or part of a class template • have an empty body • do not (implicitly) use this at all (see readability-convert-member-functions-to-static). The following real-world examples will be preserved by the check: class E1 { Pimpl &getPimpl() const; public: int &get() { // Calling a private member function disables this check. return getPimpl()->i; } ... }; class E2 { public: const int *get() const; // const_cast disables this check. S *get() { return const_cast<int*>(const_cast<const C*>(this)->get()); } ... }; After applying modifications as suggested by the check, running the check again might find more opportunities to mark member functions const. readability-misleading-indentation Correct indentation helps to understand code. Mismatch of the syntacti- cal structure and the indentation of the code may hide serious prob- lems. Missing braces can also make it significantly harder to read the code, therefore it is important to use braces. The way to avoid dangling else is to always check that an else belongs to the if that begins in the same column. You can omit braces when your inner part of e.g. an if statement has only one statement in it. Although in that case you should begin the next statement in the same column with the if. Examples: // Dangling else: if (cond1) if (cond2) foo1(); else foo2(); // Wrong indentation: else belongs to if(cond2) statement. // Missing braces: if (cond1) foo1(); foo2(); // Not guarded by if(cond1). Limitations Note that this check only works as expected when the tabs or spaces are used consistently and not mixed. readability-misplaced-array-index This check warns for unusual array index syntax. The following code has unusual array index syntax: void f(int *X, int Y) { Y[X] = 0; } becomes void f(int *X, int Y) { X[Y] = 0; } The check warns about such unusual syntax for readability reasons: • There are programmers that are not familiar with this unusual syntax. • It is possible that variables are mixed up. readability-named-parameter Find functions with unnamed arguments. The check implements the following rule originating in the Google C++ Style Guide: https://google.github.io/styleguide/cppguide.html#Function_Declarations_and_Definitions All parameters should have the same name in both the function declara- tion and definition. If a parameter is not utilized, its name can be commented out in a function definition. int doingSomething(int a, int b, int c); int doingSomething(int a, int b, int /*c*/) { // Ok: the third param is not used return a + b; } Corresponding cpplint.py check name: readability/function. readability-non-const-parameter The check finds function parameters of a pointer type that could be changed to point to a constant type instead. When const is used properly, many mistakes can be avoided. Advantages when using const properly: • prevent unintentional modification of data; • get additional warnings such as using uninitialized data; • make it easier for developers to see possible side effects. This check is not strict about constness, it only warns when the const- ness will make the function interface safer. // warning here; the declaration "const char *p" would make the function // interface safer. char f1(char *p) { return *p; } // no warning; the declaration could be more const "const int * const p" but // that does not make the function interface safer. int f2(const int *p) { return *p; } // no warning; making x const does not make the function interface safer int f3(int x) { return x; } // no warning; Technically, *p can be const ("const struct S *p"). But making // *p const could be misleading. People might think that it's safe to pass // const data to this function. struct S { int *a; int *b; }; int f3(struct S *p) { *(p->a) = 0; } // no warning; p is referenced by an lvalue. void f4(int *p) { int &x = *p; } readability-operators-representation Enforces consistent token representation for invoked binary, unary and overloaded operators in C++ code. The check supports both traditional and alternative representations of operators, such as && and and, || and or, and so on. In the realm of C++ programming, developers have the option to choose between two distinct representations for operators: traditional token representation and alternative token representation. Traditional tokens utilize symbols, such as &&, ||, and !, while alternative tokens employ more descriptive words like and, or, and not. In the following mapping table, a comprehensive list of traditional and alternative tokens, along with their corresponding representations, is presented: Token Representation Mapping Table +-------------+-------------+ | Traditional | Alternative | +-------------+-------------+ | && | and | +-------------+-------------+ | &= | and_eq | +-------------+-------------+ | & | bitand | +-------------+-------------+ | | | bitor | +-------------+-------------+ | ~ | compl | +-------------+-------------+ | ! | not | +-------------+-------------+ | != | not_eq | +-------------+-------------+ | || | or | +-------------+-------------+ | |= | or_eq | +-------------+-------------+ | ^ | xor | +-------------+-------------+ | ^= | xor_eq | +-------------+-------------+ Example // Traditional Token Representation: if (!a||!b) { // do something } // Alternative Token Representation: if (not a or not b) { // do something } Options Due to the distinct benefits and drawbacks of each representation, the default configuration doesn't enforce either. Explicit configuration is needed. To configure check to enforce Traditional Token Representation for all operators set options to &&;&=;&;|;~;!;!=;||;|=;^;^=. To configure check to enforce Alternative Token Representation for all operators set options to and;and_eq;bi- tand;bitor;compl;not;not_eq;or;or_eq;xor;xor_eq. Developers do not need to enforce all operators, and can mix the repre- sentations as desired by specifying a semicolon-separated list of both traditional and alternative tokens in the configuration, such as and;||;not. BinaryOperators This option allows you to specify a semicolon-separated list of binary operators for which you want to enforce specific token representation. The default value is empty string. OverloadedOperators This option allows you to specify a semicolon-separated list of overloaded operators for which you want to enforce specific to- ken representation. The default value is empty string. readability-qualified-auto Adds pointer qualifications to auto-typed variables that are deduced to pointers. LLVM Coding Standards advises to make it obvious if a auto typed vari- able is a pointer. This check will transform auto to auto * when the type is deduced to be a pointer. for (auto Data : MutatablePtrContainer) { change(*Data); } for (auto Data : ConstantPtrContainer) { observe(*Data); } Would be transformed into: for (auto *Data : MutatablePtrContainer) { change(*Data); } for (const auto *Data : ConstantPtrContainer) { observe(*Data); } Note const volatile qualified types will retain their const and volatile qualifiers. Pointers to pointers will not be fully qualified. const auto Foo = cast<int *>(Baz1); const auto Bar = cast<const int *>(Baz2); volatile auto FooBar = cast<int *>(Baz3); auto BarFoo = cast<int **>(Baz4); Would be transformed into: auto *const Foo = cast<int *>(Baz1); const auto *const Bar = cast<const int *>(Baz2); auto *volatile FooBar = cast<int *>(Baz3); auto *BarFoo = cast<int **>(Baz4); Options AddConstToQualified When set to true the check will add const qualifiers variables defined as auto * or auto & when applicable. Default value is true. auto Foo1 = cast<const int *>(Bar1); auto *Foo2 = cast<const int *>(Bar2); auto &Foo3 = cast<const int &>(Bar3); If AddConstToQualified is set to false, it will be transformed into: const auto *Foo1 = cast<const int *>(Bar1); auto *Foo2 = cast<const int *>(Bar2); auto &Foo3 = cast<const int &>(Bar3); Otherwise it will be transformed into: const auto *Foo1 = cast<const int *>(Bar1); const auto *Foo2 = cast<const int *>(Bar2); const auto &Foo3 = cast<const int &>(Bar3); Note in the LLVM alias, the default value is false. readability-redundant-access-specifiers Finds classes, structs, and unions containing redundant member (field and method) access specifiers. Example class Foo { public: int x; int y; public: int z; protected: int a; public: int c; } In the example above, the second public declaration can be removed without any changes of behavior. Options CheckFirstDeclaration If set to true, the check will also diagnose if the first access specifier declaration is redundant (e.g. private inside class, or public inside struct or union). Default is false. Example struct Bar { public: int x; } If CheckFirstDeclaration option is enabled, a warning about redundant access specifier will be emitted, because public is the default member access for structs. readability-redundant-casting Detects explicit type casting operations that involve the same source and destination types, and subsequently recommend their removal. Covers a range of explicit casting operations, including static_cast, const_cast, C-style casts, and reinterpret_cast. Its primary objective is to enhance code readability and maintainability by eliminating un- necessary type casting. int value = 42; int result = static_cast<int>(value); In this example, the static_cast<int>(value) is redundant, as it per- forms a cast from an int to another int. Casting operations involving constructor conversions, user-defined con- versions, functional casts, type-dependent casts, casts between dis- tinct type aliases that refer to the same underlying type, as well as bitfield-related casts and casts directly from lvalue to rvalue, are all disregarded by the check. Options IgnoreMacros If set to true, the check will not give warnings inside macros. Default is true. IgnoreTypeAliases When set to false, the check will consider type aliases, and when set to true, it will resolve all type aliases and operate on the underlying types. Default is false. readability-redundant-control-flow This check looks for procedures (functions returning no value) with re- turn statements at the end of the function. Such return statements are redundant. Loop statements (for, while, do while) are checked for redundant con- tinue statements at the end of the loop body. Examples: The following function f contains a redundant return statement: extern void g(); void f() { g(); return; } becomes extern void g(); void f() { g(); } The following function k contains a redundant continue statement: void k() { for (int i = 0; i < 10; ++i) { continue; } } becomes void k() { for (int i = 0; i < 10; ++i) { } } readability-redundant-declaration Finds redundant variable and function declarations. extern int X; extern int X; becomes extern int X; Such redundant declarations can be removed without changing program be- havior. They can for instance be unintentional left overs from previ- ous refactorings when code has been moved around. Having redundant dec- larations could in worst case mean that there are typos in the code that cause bugs. Normally the code can be automatically fixed, clang-tidy can remove the second declaration. However there are 2 cases when you need to fix the code manually: • When the declarations are in different header files; • When multiple variables are declared together. Options IgnoreMacros If set to true, the check will not give warnings inside macros. Default is true. readability-redundant-function-ptr-dereference Finds redundant dereferences of a function pointer. Before: int f(int,int); int (*p)(int, int) = &f; int i = (**p)(10, 50); After: int f(int,int); int (*p)(int, int) = &f; int i = (*p)(10, 50); readability-redundant-inline-specifier Detects redundant inline specifiers on function and variable declara- tions. Examples: constexpr inline void f() {} In the example above the keyword inline is redundant since constexpr functions are implicitly inlined class MyClass { inline void myMethod() {} }; In the example above the keyword inline is redundant since member func- tions defined entirely inside a class/struct/union definition are im- plicitly inlined. Options StrictMode If set to true, the check will also flag functions and variables that already have internal linkage as redundant. readability-redundant-member-init Finds member initializations that are unnecessary because the same de- fault constructor would be called if they were not present. Example // Explicitly initializing the member s and v is unnecessary. class Foo { public: Foo() : s() {} private: std::string s; std::vector<int> v {}; }; Options IgnoreBaseInCopyConstructors Default is false. When true, the check will ignore unnecessary base class initial- izations within copy constructors, since some compilers issue warnings/errors when base classes are not explicitly initialized in copy constructors. For example, gcc with -Wextra or -Wer- ror=extra issues warning or error base class 'Bar' should be ex- plicitly initialized in the copy constructor if Bar() were re- moved in the following example: // Explicitly initializing member s and base class Bar is unnecessary. struct Foo : public Bar { // Remove s() below. If IgnoreBaseInCopyConstructors!=0, keep Bar(). Foo(const Foo& foo) : Bar(), s() {} std::string s; }; readability-redundant-preprocessor Finds potentially redundant preprocessor directives. At the moment the following cases are detected: • #ifdef .. #endif pairs which are nested inside an outer pair with the same condition. For example: #ifdef FOO #ifdef FOO // inner ifdef is considered redundant void f(); #endif #endif • Same for #ifndef .. #endif pairs. For example: #ifndef FOO #ifndef FOO // inner ifndef is considered redundant void f(); #endif #endif • #ifndef inside an #ifdef with the same condition: #ifdef FOO #ifndef FOO // inner ifndef is considered redundant void f(); #endif #endif • #ifdef inside an #ifndef with the same condition: #ifndef FOO #ifdef FOO // inner ifdef is considered redundant void f(); #endif #endif • #if .. #endif pairs which are nested inside an outer pair with the same condition. For example: #define FOO 4 #if FOO == 4 #if FOO == 4 // inner if is considered redundant void f(); #endif #endif readability-redundant-smartptr-get Find and remove redundant calls to smart pointer's .get() method. Examples: ptr.get()->Foo() ==> ptr->Foo() *ptr.get() ==> *ptr *ptr->get() ==> **ptr if (ptr.get() == nullptr) ... => if (ptr == nullptr) ... IgnoreMacros If this option is set to true (default is true), the check will not warn about calls inside macros. readability-redundant-string-cstr Finds unnecessary calls to std::string::c_str() and std::string::data(). Options StringParameterFunctions A semicolon-separated list of (fully qualified) func- tion/method/operator names, with the requirement that any para- meter currently accepting a const char* input should also be able to accept std::string inputs, or proper overload candidates that can do so should exist. This can be used to configure func- tions such as fmt::format, spdlog::logger::info, or wrappers around these and similar functions. The default value is the empty string. readability-redundant-string-init Finds unnecessary string initializations. Examples // Initializing string with empty string literal is unnecessary. std::string a = ""; std::string b(""); // becomes std::string a; std::string b; // Initializing a string_view with an empty string literal produces an // instance that compares equal to string_view(). std::string_view a = ""; std::string_view b(""); // becomes std::string_view a; std::string_view b; Options StringNames Default is ::std::basic_string;::std::basic_string_view. Semicolon-delimited list of class names to apply this check to. By default ::std::basic_string applies to std::string and std::wstring. Set to e.g. ::std::ba- sic_string;llvm::StringRef;QString to perform this check on cus- tom classes. readability-reference-to-constructed-temporary Detects C++ code where a reference variable is used to extend the life- time of a temporary object that has just been constructed. This construction is often the result of multiple code refactorings or a lack of developer knowledge, leading to confusion or subtle bugs. In most cases, what the developer really wanted to do is create a new variable rather than extending the lifetime of a temporary object. Examples of problematic code include: const std::string& str("hello"); struct Point { int x; int y; }; const Point& p = { 1, 2 }; In the first example, a const std::string& reference variable str is assigned a temporary object created by the std::string("hello") con- structor. In the second example, a const Point& reference variable p is assigned an object that is constructed from an initializer list { 1, 2 }. Both of these examples extend the lifetime of the temporary object to the lifetime of the reference variable, which can make it difficult to reason about and may lead to subtle bugs or misunderstanding. To avoid these issues, it is recommended to change the reference vari- able to a (const) value variable. readability-simplify-boolean-expr Looks for boolean expressions involving boolean constants and simpli- fies them to use the appropriate boolean expression directly. Simpli- fies boolean expressions by application of DeMorgan's Theorem. Examples: +----------------------------+------------+ | Initial expression | Result | +----------------------------+------------+ | if (b == true) | if (b) | +----------------------------+------------+ | if (b == false) | if (!b) | +----------------------------+------------+ | if (b && true) | if (b) | +----------------------------+------------+ | if (b && false) | if (false) | +----------------------------+------------+ | if (b || true) | if (true) | +----------------------------+------------+ | if (b || false) | if (b) | +----------------------------+------------+ | e ? true : false | e | +----------------------------+------------+ | e ? false : true | !e | +----------------------------+------------+ | if (true) t(); else f(); | t(); | +----------------------------+------------+ | if (false) t(); else f(); | f(); | +----------------------------+------------+ | if (e) return true; else | return e; | | return false; | | +----------------------------+------------+ | if (e) return false; else | return !e; | | return true; | | +----------------------------+------------+ | if (e) b = true; else b = | b = e; | | false; | | +----------------------------+------------+ | if (e) b = false; else b = | b = !e; | | true; | | +----------------------------+------------+ | if (e) return true; return | return e; | | false; | | +----------------------------+------------+ | if (e) return false; re- | return !e; | | turn true; | | +----------------------------+------------+ | !(!a || b) | a && !b | +----------------------------+------------+ | !(a || !b) | !a && b | +----------------------------+------------+ | !(!a || !b) | a && b | +----------------------------+------------+ | !(!a && b) | a || !b | +----------------------------+------------+ | !(a && !b) | !a || b | +----------------------------+------------+ | !(!a && !b) | a || b | +----------------------------+------------+ The resulting expression e is modified as follows: 1. Unnecessary parentheses around the expression are removed. 2. Negated applications of ! are eliminated. 3. Negated applications of comparison operators are changed to use the opposite condition. 4. Implicit conversions of pointers, including pointers to mem- bers, to bool are replaced with explicit comparisons to nullptr in C++11 or NULL in C++98/03. 5. Implicit casts to bool are replaced with explicit casts to bool. 6. Object expressions with explicit operator bool conversion op- erators are replaced with explicit casts to bool. 7. Implicit conversions of integral types to bool are replaced with explicit comparisons to 0. Examples: 1. The ternary assignment bool b = (i < 0) ? true : false; has redundant parentheses and becomes bool b = i < 0;. 2. The conditional return if (!b) return false; return true; has an implied double negation and becomes return b;. 3. The conditional return if (i < 0) return false; return true; becomes return i >= 0;. The conditional return if (i != 0) return false; return true; becomes return i == 0;. 4. The conditional return if (p) return true; return false; has an implicit conversion of a pointer to bool and becomes re- turn p != nullptr;. The ternary assignment bool b = (i & 1) ? true : false; has an implicit conversion of i & 1 to bool and becomes bool b = (i & 1) != 0;. 5. The conditional return if (i & 1) return true; else return false; has an implicit conversion of an integer quantity i & 1 to bool and becomes return (i & 1) != 0; 6. Given struct X { explicit operator bool(); };, and an in- stance x of struct X, the conditional return if (x) return true; return false; becomes return static_cast<bool>(x); Options IgnoreMacros If true, ignore boolean expressions originating from expanded macros. Default is false. ChainedConditionalReturn If true, conditional boolean return statements at the end of an if/else if chain will be transformed. Default is false. ChainedConditionalAssignment If true, conditional boolean assignments at the end of an if/else if chain will be transformed. Default is false. SimplifyDeMorgan If true, DeMorgan's Theorem will be applied to simplify negated conjunctions and disjunctions. Default is true. SimplifyDeMorganRelaxed If true, SimplifyDeMorgan will also transform negated conjunc- tions and disjunctions where there is no negation on either operand. This option has no effect if SimplifyDeMorgan is false. Default is false. When Enabled: bool X = !(A && B) bool Y = !(A || B) Would be transformed to: bool X = !A || !B bool Y = !A && !B readability-simplify-subscript-expr This check simplifies subscript expressions. Currently this covers calling .data() and immediately doing an array subscript operation to obtain a single element, in which case simply calling operator[] suf- fice. Examples: std::string s = ...; char c = s.data()[i]; // char c = s[i]; Options Types The list of type(s) that triggers this check. Default is ::std::basic_string;::std::basic_string_view;::std::vec- tor;::std::array;::std::span readability-static-accessed-through-instance Checks for member expressions that access static members through in- stances, and replaces them with uses of the appropriate qualified-id. Example: The following code: struct C { static void foo(); static int x; enum { E1 }; enum E { E2 }; }; C *c1 = new C(); c1->foo(); c1->x; c1->E1; c1->E2; is changed to: C *c1 = new C(); C::foo(); C::x; C::E1; C::E2; readability-static-definition-in-anonymous-namespace Finds static function and variable definitions in anonymous namespace. In this case, static is redundant, because anonymous namespace limits the visibility of definitions to a single translation unit. namespace { static int a = 1; // Warning. static const int b = 1; // Warning. namespace inner { static int c = 1; // Warning. } } The check will apply a fix by removing the redundant static qualifier. readability-string-compare Finds string comparisons using the compare method. A common mistake is to use the string's compare method instead of using the equality or inequality operators. The compare method is intended for sorting functions and thus returns a negative number, a positive number or zero depending on the lexicographical relationship between the strings compared. If an equality or inequality check can suffice, that is recommended. This is recommended to avoid the risk of incorrect interpretation of the return value and to simplify the code. The string equality and inequality operators can also be faster than the compare method due to early termination. Examples: std::string str1{"a"}; std::string str2{"b"}; // use str1 != str2 instead. if (str1.compare(str2)) { } // use str1 == str2 instead. if (!str1.compare(str2)) { } // use str1 == str2 instead. if (str1.compare(str2) == 0) { } // use str1 != str2 instead. if (str1.compare(str2) != 0) { } // use str1 == str2 instead. if (0 == str1.compare(str2)) { } // use str1 != str2 instead. if (0 != str1.compare(str2)) { } // Use str1 == "foo" instead. if (str1.compare("foo") == 0) { } The above code examples show the list of if-statements that this check will give a warning for. All of them uses compare to check if equality or inequality of two strings instead of using the correct operators. readability-suspicious-call-argument Finds function calls where the arguments passed are provided out of or- der, based on the difference between the argument name and the parame- ter names of the function. Given a function call f(foo, bar); and a function signature void f(T tvar, U uvar), the arguments foo and bar are swapped if foo (the argu- ment name) is more similar to uvar (the other parameter) than tvar (the parameter it is currently passed to) and bar is more similar to tvar than uvar. Warnings might indicate either that the arguments are swapped, or that the names' cross-similarity might hinder code comprehension. Heuristics The following heuristics are implemented in the check. If any of the enabled heuristics deem the arguments to be provided out of order, a warning will be issued. The heuristics themselves are implemented by considering pairs of strings, and are symmetric, so in the following there is no distinction on which string is the argument name and which string is the parameter name. Equality The most trivial heuristic, which compares the two strings for case-in- sensitive equality. Abbreviation Common abbreviations can be specified which will deem the strings simi- lar if the abbreviated and the abbreviation stand together. For exam- ple, if src is registered as an abbreviation for source, then the fol- lowing code example will be warned about. void foo(int source, int x); foo(b, src); The abbreviations to recognise can be configured with the Abbreviations check option. This heuristic is case-insensitive. Prefix The prefix heuristic reports if one of the strings is a sufficiently long prefix of the other string, e.g. target to targetPtr. The simi- larity percentage is the length ratio of the prefix to the longer string, in the previous example, it would be 6 / 9 = 66.66...%. This heuristic can be configured with bounds. The default bounds are: below 25% dissimilar and above 30% similar. This heuristic is case-in- sensitive. Suffix Analogous to the Prefix heuristic. In the case of oldValue and value compared, the similarity percentage is 8 / 5 = 62.5%. This heuristic can be configured with bounds. The default bounds are: below 25% dissimilar and above 30% similar. This heuristic is case-in- sensitive. Substring The substring heuristic combines the prefix and the suffix heuristic, and tries to find the longest common substring in the two strings pro- vided. The similarity percentage is the ratio of the found longest common substring against the longer of the two input strings. For ex- ample, given val and rvalue, the similarity is 3 / 6 = 50%. If no characters are common in the two string, 0%. This heuristic can be configured with bounds. The default bounds are: below 40% dissimilar and above 50% similar. This heuristic is case-in- sensitive. Levenshtein distance (as Levenshtein) The Levenshtein distance describes how many single-character changes (additions, changes, or removals) must be applied to transform one string into another. The Levenshtein distance is translated into a similarity percentage by dividing it with the length of the longer string, and taking its com- plement with regards to 100%. For example, given something and any- thing, the distance is 4 edits, and the similarity percentage is 100% - 4 / 9 = 55.55...%. This heuristic can be configured with bounds. The default bounds are: below 50% dissimilar and above 66% similar. This heuristic is case-sensitive. Jaro--Winkler distance (as JaroWinkler) The Jaro--Winkler distance is an edit distance like the Levenshtein distance. It is calculated from the amount of common characters that are sufficiently close to each other in position, and to-be-changed characters. The original definition of Jaro has been extended by Win- kler to weigh prefix similarities more. The similarity percentage is expressed as an average of the common and non-common characters against the length of both strings. This heuristic can be configured with bounds. The default bounds are: below 75% dissimilar and above 85% similar. This heuristic is case-in- sensitive. Srensen--Dice coefficient (as Dice) The Srensen--Dice coefficient was originally defined to measure the similarity of two sets. Formally, the coefficient is calculated by di- viding 2 * #(intersection) with #(set1) + #(set2), where #() is the cardinality function of sets. This metric is applied to strings by creating bigrams (substring sequences of length 2) of the two strings and using the set of bigrams for the two strings as the two sets. This heuristic can be configured with bounds. The default bounds are: below 60% dissimilar and above 70% similar. This heuristic is case-in- sensitive. Options MinimumIdentifierNameLength Sets the minimum required length the argument and parameter names need to have. Names shorter than this length will be ig- nored. Defaults to 3. Abbreviations For the Abbreviation heuristic (see here), this option config- ures the abbreviations in the "abbreviation=abbreviated_value" format. The option is a string, with each value joined by ";". By default, the following abbreviations are set: • addr=address • arr=array • attr=attribute • buf=buffer • cl=client • cnt=count • col=column • cpy=copy • dest=destination • dist=distance • dst=distance • elem=element • hght=height • i=index • idx=index • len=length • ln=line • lst=list • nr=number • num=number • pos=position • ptr=pointer • ref=reference • src=source • srv=server • stmt=statement • str=string • val=value • var=variable • vec=vector • wdth=width The configuration options for each implemented heuristic (see above) is constructed dynamically. In the following, <HeuristicName> refers to one of the keys from the heuristics implemented. <HeuristicName> True or False, whether a particular heuristic, such as Equality or Levenshtein is enabled. Defaults to True for every heuristic. <HeuristicName>DissimilarBelow, <HeuristicName>SimilarAbove A value between 0 and 100, expressing a percentage. The bounds set what percentage of similarity the heuristic must deduce for the two identifiers to be considered similar or dissimilar by the check. Given arguments arg1 and arg2 passed to param1 and param2, re- spectively, the bounds check is performed in the following way: If the similarity of the currently passed argument order (arg1 to param1) is below the DissimilarBelow threshold, and the simi- larity of the suggested swapped order (arg1 to param2) is above the SimilarAbove threshold, the swap is reported. For the defaults of each heuristic, see above. Name synthesis When comparing the argument names and parameter names, the following logic is used to gather the names for comparison: Parameter names are the identifiers as written in the source code. Argument names are: • If a variable is passed, the variable's name. • If a subsequent function call's return value is used as argument, the called function's name. • Otherwise, empty string. Empty argument or parameter names are ignored by the heuristics. readability-uniqueptr-delete-release Replace delete <unique_ptr>.release() with <unique_ptr> = nullptr. The latter is shorter, simpler and does not require use of raw pointer APIs. std::unique_ptr<int> P; delete P.release(); // becomes std::unique_ptr<int> P; P = nullptr; Options PreferResetCall If true, refactor by calling the reset member function instead of assigning to nullptr. Default value is false. std::unique_ptr<int> P; delete P.release(); // becomes std::unique_ptr<int> P; P.reset(); readability-uppercase-literal-suffix cert-dcl16-c redirects here as an alias for this check. By default, only the suffixes that begin with l (l, ll, lu, llu, but not u, ul, ull) are diagnosed by that alias. hicpp-uppercase-literal-suffix redirects here as an alias for this check. Detects when the integral literal or floating point (decimal or hexa- decimal) literal has a non-uppercase suffix and provides a fix-it hint with the uppercase suffix. All valid combinations of suffixes are supported. auto x = 1; // OK, no suffix. auto x = 1u; // warning: integer literal suffix 'u' is not upper-case auto x = 1U; // OK, suffix is uppercase. ... Options NewSuffixes Optionally, a list of the destination suffixes can be provided. When the suffix is found, a case-insensitive lookup in that list is made, and if a replacement is found that is different from the current suffix, then the diagnostic is issued. This allows for fine-grained control of what suffixes to consider and what their replacements should be. Example Given a list L;uL: • l -> L • L will be kept as is. • ul -> uL • Ul -> uL • UL -> uL • uL will be kept as is. • ull will be kept as is, since it is not in the list • and so on. IgnoreMacros If this option is set to true (default is true), the check will not warn about literal suffixes inside macros. readability-use-anyofallof Finds range-based for loops that can be replaced by a call to std::any_of or std::all_of. In C++ 20 mode, suggests std::ranges::any_of or std::ranges::all_of. Example: bool all_even(std::vector<int> V) { for (int I : V) { if (I % 2) return false; } return true; // Replace loop by // return std::ranges::all_of(V, [](int I) { return I % 2 == 0; }); } zircon-temporary-objects Warns on construction of specific temporary objects in the Zircon ker- nel. If the object should be flagged, If the object should be flagged, the fully qualified type name must be explicitly passed to the check. For example, given the list of classes "Foo" and "NS::Bar", all of the following will trigger the warning: Foo(); Foo F = Foo(); func(Foo()); namespace NS { Bar(); } With the same list, the following will not trigger the warning: Foo F; // Non-temporary construction okay Foo F(param); // Non-temporary construction okay Foo *F = new Foo(); // New construction okay Bar(); // Not NS::Bar, so okay NS::Bar B; // Non-temporary construction okay Note that objects must be explicitly specified in order to be flagged, and so objects that inherit a specified object will not be flagged. This check matches temporary objects without regard for inheritance and so a prohibited base class type does not similarly prohibit derived class types. class Derived : Foo {} // Derived is not explicitly disallowed Derived(); // and so temporary construction is okay Options Names A semi-colon-separated list of fully-qualified names of C++ classes that should not be constructed as temporaries. Default is empty. +--------------------------------------------------------+--------------+ | Name | Offers fixes | +--------------------------------------------------------+--------------+ | abseil-cleanup-ctad | Yes | +--------------------------------------------------------+--------------+ | abseil-duration-addition | Yes | +--------------------------------------------------------+--------------+ | abseil-duration-comparison | Yes | +--------------------------------------------------------+--------------+ | abseil-duration-conversion-cast | Yes | +--------------------------------------------------------+--------------+ | abseil-duration-division | Yes | +--------------------------------------------------------+--------------+ | abseil-duration-factory-float | Yes | +--------------------------------------------------------+--------------+ | abseil-duration-factory-scale | Yes | +--------------------------------------------------------+--------------+ | abseil-duration-subtraction | Yes | +--------------------------------------------------------+--------------+ | abseil-duration-unnecessary-conversion | Yes | +--------------------------------------------------------+--------------+ | abseil-faster-strsplit-delimiter | Yes | +--------------------------------------------------------+--------------+ | abseil-no-internal-dependencies | | +--------------------------------------------------------+--------------+ | abseil-no-namespace | | +--------------------------------------------------------+--------------+ | abseil-redundant-strcat-calls | Yes | +--------------------------------------------------------+--------------+ | abseil-str-cat-append | Yes | +--------------------------------------------------------+--------------+ | abseil-string-find-startswith | Yes | +--------------------------------------------------------+--------------+ | abseil-string-find-str-contains | Yes | +--------------------------------------------------------+--------------+ | abseil-time-comparison | Yes | +--------------------------------------------------------+--------------+ | abseil-time-subtraction | Yes | +--------------------------------------------------------+--------------+ | abseil-upgrade-duration-conversions | Yes | +--------------------------------------------------------+--------------+ | altera-id-dependent-backward-branch | | +--------------------------------------------------------+--------------+ | altera-kernel-name-restriction | | +--------------------------------------------------------+--------------+ | altera-single-work-item-barrier | | +--------------------------------------------------------+--------------+ | altera-struct-pack-align | Yes | +--------------------------------------------------------+--------------+ | altera-unroll-loops | | +--------------------------------------------------------+--------------+ | android-cloexec-accept | Yes | +--------------------------------------------------------+--------------+ | android-cloexec-accept4 | Yes | +--------------------------------------------------------+--------------+ | android-cloexec-creat | Yes | +--------------------------------------------------------+--------------+ | android-cloexec-dup | Yes | +--------------------------------------------------------+--------------+ | android-cloexec-epoll-create | Yes | +--------------------------------------------------------+--------------+ | android-cloexec-epoll-create1 | Yes | +--------------------------------------------------------+--------------+ | android-cloexec-fopen | Yes | +--------------------------------------------------------+--------------+ | android-cloexec-inotify-init | Yes | +--------------------------------------------------------+--------------+ | android-cloexec-inotify-init1 | Yes | +--------------------------------------------------------+--------------+ | android-cloexec-memfd-create | Yes | +--------------------------------------------------------+--------------+ | android-cloexec-open | Yes | +--------------------------------------------------------+--------------+ | android-cloexec-pipe | Yes | +--------------------------------------------------------+--------------+ | android-cloexec-pipe2 | Yes | +--------------------------------------------------------+--------------+ | android-cloexec-socket | Yes | +--------------------------------------------------------+--------------+ | android-comparison-in-temp-failure-retry | | +--------------------------------------------------------+--------------+ | boost-use-to-string | Yes | +--------------------------------------------------------+--------------+ | bugprone-argument-comment | Yes | +--------------------------------------------------------+--------------+ | bugprone-assert-side-effect | | +--------------------------------------------------------+--------------+ | bugprone-assignment-in-if-condition | | +--------------------------------------------------------+--------------+ | bugprone-bad-signal-to-kill-thread | | +--------------------------------------------------------+--------------+ | bugprone-bool-pointer-implicit-conversion | Yes | +--------------------------------------------------------+--------------+ | bugprone-branch-clone | | +--------------------------------------------------------+--------------+ | bugprone-casting-through-void | | +--------------------------------------------------------+--------------+ | bugprone-chained-comparison | | +--------------------------------------------------------+--------------+ | bugprone-compare-pointer-to-member-virtual-function | | +--------------------------------------------------------+--------------+ | bugprone-copy-constructor-init | Yes | +--------------------------------------------------------+--------------+ | bugprone-dangling-handle | | +--------------------------------------------------------+--------------+ | bugprone-dynamic-static-initializers | | +--------------------------------------------------------+--------------+ | bugprone-easily-swappable-parameters | | +--------------------------------------------------------+--------------+ | bugprone-empty-catch | | +--------------------------------------------------------+--------------+ | bugprone-exception-escape | | +--------------------------------------------------------+--------------+ | bugprone-fold-init-type | | +--------------------------------------------------------+--------------+ | bugprone-forward-declaration-namespace | | +--------------------------------------------------------+--------------+ | bugprone-forwarding-reference-overload | | +--------------------------------------------------------+--------------+ | bugprone-implicit-widening-of-multiplication-result | Yes | +--------------------------------------------------------+--------------+ | bugprone-inaccurate-erase | Yes | +--------------------------------------------------------+--------------+ | bugprone-inc-dec-in-conditions | | +--------------------------------------------------------+--------------+ | bugprone-incorrect-enable-if | Yes | +--------------------------------------------------------+--------------+ | bugprone-incorrect-roundings | | +--------------------------------------------------------+--------------+ | bugprone-infinite-loop | | +--------------------------------------------------------+--------------+ | bugprone-integer-division | | +--------------------------------------------------------+--------------+ | bugprone-lambda-function-name | | +--------------------------------------------------------+--------------+ | bugprone-macro-parentheses | Yes | +--------------------------------------------------------+--------------+ | bugprone-macro-repeated-side-effects | | +--------------------------------------------------------+--------------+ | bugprone-misplaced-operator-in-strlen-in-alloc | Yes | +--------------------------------------------------------+--------------+ | bugprone-misplaced-pointer-arithmetic-in-alloc | Yes | +--------------------------------------------------------+--------------+ | bugprone-misplaced-widening-cast | | +--------------------------------------------------------+--------------+ | bugprone-move-forwarding-reference | Yes | +--------------------------------------------------------+--------------+ | bugprone-multi-level-implicit-pointer-conversion | | +--------------------------------------------------------+--------------+ | bugprone-multiple-new-in-one-expression | | +--------------------------------------------------------+--------------+ | bugprone-multiple-statement-macro | | +--------------------------------------------------------+--------------+ | bugprone-no-escape | | +--------------------------------------------------------+--------------+ | bugprone-non-zero-enum-to-bool-conversion | | +--------------------------------------------------------+--------------+ | bugprone-not-null-terminated-result | Yes | +--------------------------------------------------------+--------------+ | bugprone-optional-value-conversion | Yes | +--------------------------------------------------------+--------------+ | bugprone-parent-virtual-call | Yes | +--------------------------------------------------------+--------------+ | bugprone-posix-return | Yes | +--------------------------------------------------------+--------------+ | bugprone-redundant-branch-condition | Yes | +--------------------------------------------------------+--------------+ | bugprone-reserved-identifier | Yes | +--------------------------------------------------------+--------------+ | bugprone-shared-ptr-array-mismatch | Yes | +--------------------------------------------------------+--------------+ | bugprone-signal-handler | | +--------------------------------------------------------+--------------+ | bugprone-signed-char-misuse | | +--------------------------------------------------------+--------------+ | bugprone-sizeof-container | | +--------------------------------------------------------+--------------+ | bugprone-sizeof-expression | | +--------------------------------------------------------+--------------+ | bugprone-spuriously-wake-up-functions | | +--------------------------------------------------------+--------------+ | bugprone-standalone-empty | Yes | +--------------------------------------------------------+--------------+ | bugprone-string-constructor | Yes | +--------------------------------------------------------+--------------+ | bugprone-string-integer-assignment | Yes | +--------------------------------------------------------+--------------+ | bugprone-string-literal-with-embedded-nul | | +--------------------------------------------------------+--------------+ | bugprone-stringview-nullptr | Yes | +--------------------------------------------------------+--------------+ | bugprone-suspicious-enum-usage | | +--------------------------------------------------------+--------------+ | bugprone-suspicious-include | | +--------------------------------------------------------+--------------+ | bugprone-suspicious-memory-comparison | | +--------------------------------------------------------+--------------+ | bugprone-suspicious-memset-usage | Yes | +--------------------------------------------------------+--------------+ | bugprone-suspicious-missing-comma | | +--------------------------------------------------------+--------------+ | bugprone-suspicious-realloc-usage | | +--------------------------------------------------------+--------------+ | bugprone-suspicious-semicolon | Yes | +--------------------------------------------------------+--------------+ | bugprone-suspicious-string-compare | Yes | +--------------------------------------------------------+--------------+ | bugprone-swapped-arguments | Yes | +--------------------------------------------------------+--------------+ | bugprone-switch-missing-default-case | | +--------------------------------------------------------+--------------+ | bugprone-terminating-continue | Yes | +--------------------------------------------------------+--------------+ | bugprone-throw-keyword-missing | | +--------------------------------------------------------+--------------+ | bugprone-too-small-loop-variable | | +--------------------------------------------------------+--------------+ | bugprone-unchecked-optional-access | | +--------------------------------------------------------+--------------+ | bugprone-undefined-memory-manipulation | | +--------------------------------------------------------+--------------+ | bugprone-undelegated-constructor | | +--------------------------------------------------------+--------------+ | bugprone-unhandled-exception-at-new | | +--------------------------------------------------------+--------------+ | bugprone-unhandled-self-assignment | | +--------------------------------------------------------+--------------+ | bugprone-unique-ptr-array-mismatch | Yes | +--------------------------------------------------------+--------------+ | bugprone-unsafe-functions | | +--------------------------------------------------------+--------------+ | bugprone-unused-local-non-trivial-variable | | +--------------------------------------------------------+--------------+ | bugprone-unused-raii | Yes | +--------------------------------------------------------+--------------+ | bugprone-unused-return-value | | +--------------------------------------------------------+--------------+ | bugprone-use-after-move | | +--------------------------------------------------------+--------------+ | bugprone-virtual-near-miss | Yes | +--------------------------------------------------------+--------------+ | cert-dcl21-cpp | Yes | +--------------------------------------------------------+--------------+ | cert-dcl50-cpp | | +--------------------------------------------------------+--------------+ | cert-dcl58-cpp | | +--------------------------------------------------------+--------------+ | cert-env33-c | | +--------------------------------------------------------+--------------+ | cert-err33-c | | +--------------------------------------------------------+--------------+ | cert-err34-c | | +--------------------------------------------------------+--------------+ | cert-err52-cpp | | +--------------------------------------------------------+--------------+ | cert-err58-cpp | | +--------------------------------------------------------+--------------+ | cert-err60-cpp | | +--------------------------------------------------------+--------------+ | cert-flp30-c | | +--------------------------------------------------------+--------------+ | cert-mem57-cpp | | +--------------------------------------------------------+--------------+ | cert-msc50-cpp | | +--------------------------------------------------------+--------------+ | cert-msc51-cpp | | +--------------------------------------------------------+--------------+ | cert-oop57-cpp | | +--------------------------------------------------------+--------------+ | cert-oop58-cpp | | +--------------------------------------------------------+--------------+ | concurrency-mt-unsafe | | +--------------------------------------------------------+--------------+ | concurrency-thread-canceltype-asynchronous | | +--------------------------------------------------------+--------------+ | cppcoreguidelines-avoid-capturing-lambda-coroutines | | +--------------------------------------------------------+--------------+ | cppcoreguidelines-avoid-const-or-ref-data-members | | +--------------------------------------------------------+--------------+ | cppcoreguidelines-avoid-do-while | | +--------------------------------------------------------+--------------+ | cppcoreguidelines-avoid-goto | | +--------------------------------------------------------+--------------+ | cppcoreguidelines-avoid-non-const-global-variables | | +--------------------------------------------------------+--------------+ | cppcoreguidelines-avoid-reference-coroutine-parameters | | +--------------------------------------------------------+--------------+ | cppcoreguidelines-init-variables | Yes | +--------------------------------------------------------+--------------+ | cppcoreguidelines-interfaces-global-init | | +--------------------------------------------------------+--------------+ | cppcoreguidelines-macro-usage | | +--------------------------------------------------------+--------------+ | cppcoreguidelines-misleading-capture-default-by-value | Yes | +--------------------------------------------------------+--------------+ | cppcoreguidelines-missing-std-forward | | +--------------------------------------------------------+--------------+ | cppcoreguidelines-narrowing-conversions | | +--------------------------------------------------------+--------------+ | cppcoreguidelines-no-malloc | | +--------------------------------------------------------+--------------+ | cppcoreguidelines-no-suspend-with-lock | | +--------------------------------------------------------+--------------+ | cppcoreguidelines-owning-memory | | +--------------------------------------------------------+--------------+ | cppcoreguidelines-prefer-member-initializer | Yes | +--------------------------------------------------------+--------------+ | cppcoreguidelines-pro-bounds-array-to-pointer-decay | | +--------------------------------------------------------+--------------+ | cppcoreguidelines-pro-bounds-constant-array-index | Yes | +--------------------------------------------------------+--------------+ | cppcoreguidelines-pro-bounds-pointer-arithmetic | | +--------------------------------------------------------+--------------+ | cppcoreguidelines-pro-type-const-cast | | +--------------------------------------------------------+--------------+ | cppcoreguidelines-pro-type-cstyle-cast | Yes | +--------------------------------------------------------+--------------+ | cppcoreguidelines-pro-type-member-init | Yes | +--------------------------------------------------------+--------------+ | cppcoreguidelines-pro-type-reinterpret-cast | | +--------------------------------------------------------+--------------+ | cppcoreguidelines-pro-type-static-cast-downcast | Yes | +--------------------------------------------------------+--------------+ | cppcoreguidelines-pro-type-union-access | | +--------------------------------------------------------+--------------+ | cppcoreguidelines-pro-type-vararg | | +--------------------------------------------------------+--------------+ | cppcoreguidelines-rvalue-reference-param-not-moved | | +--------------------------------------------------------+--------------+ | cppcoreguidelines-slicing | | +--------------------------------------------------------+--------------+ | cppcoreguidelines-special-member-functions | | +--------------------------------------------------------+--------------+ | cppcoreguidelines-virtual-class-destructor | Yes | +--------------------------------------------------------+--------------+ | darwin-avoid-spinlock | | +--------------------------------------------------------+--------------+ | darwin-dispatch-once-nonstatic | Yes | +--------------------------------------------------------+--------------+ | fuchsia-default-arguments-calls | | +--------------------------------------------------------+--------------+ | fuchsia-default-arguments-declarations | Yes | +--------------------------------------------------------+--------------+ | fuchsia-multiple-inheritance | | +--------------------------------------------------------+--------------+ | fuchsia-overloaded-operator | | +--------------------------------------------------------+--------------+ | fuchsia-statically-constructed-objects | | +--------------------------------------------------------+--------------+ | fuchsia-trailing-return | | +--------------------------------------------------------+--------------+ | fuchsia-virtual-inheritance | | +--------------------------------------------------------+--------------+ | google-build-explicit-make-pair | | +--------------------------------------------------------+--------------+ | google-build-namespaces | | +--------------------------------------------------------+--------------+ | google-build-using-namespace | | +--------------------------------------------------------+--------------+ | google-default-arguments | | +--------------------------------------------------------+--------------+ | google-explicit-constructor | Yes | +--------------------------------------------------------+--------------+ | google-global-names-in-headers | | +--------------------------------------------------------+--------------+ | google-objc-avoid-nsobject-new | | +--------------------------------------------------------+--------------+ | google-objc-avoid-throwing-exception | | +--------------------------------------------------------+--------------+ | google-objc-function-naming | | +--------------------------------------------------------+--------------+ | google-objc-global-variable-declaration | | +--------------------------------------------------------+--------------+ | google-readability-avoid-underscore-in-googletest-name | | +--------------------------------------------------------+--------------+ | google-readability-casting | | +--------------------------------------------------------+--------------+ | google-readability-todo | | +--------------------------------------------------------+--------------+ | google-runtime-int | | +--------------------------------------------------------+--------------+ | google-runtime-operator | | +--------------------------------------------------------+--------------+ | google-upgrade-googletest-case | Yes | +--------------------------------------------------------+--------------+ | hicpp-exception-baseclass | | +--------------------------------------------------------+--------------+ | hicpp-ignored-remove-result | | +--------------------------------------------------------+--------------+ | hicpp-multiway-paths-covered | | +--------------------------------------------------------+--------------+ | hicpp-no-assembler | | +--------------------------------------------------------+--------------+ | hicpp-signed-bitwise | | +--------------------------------------------------------+--------------+ | linuxkernel-must-use-errs | | +--------------------------------------------------------+--------------+ | llvm-header-guard | | +--------------------------------------------------------+--------------+ | llvm-include-order | Yes | +--------------------------------------------------------+--------------+ | llvm-namespace-comment | | +--------------------------------------------------------+--------------+ | llvm-prefer-isa-or-dyn-cast-in-conditionals | Yes | +--------------------------------------------------------+--------------+ | llvm-prefer-register-over-unsigned | Yes | +--------------------------------------------------------+--------------+ | llvm-twine-local | Yes | +--------------------------------------------------------+--------------+ | llvmlibc-callee-namespace | | +--------------------------------------------------------+--------------+ | llvmlibc-implementation-in-namespace | | +--------------------------------------------------------+--------------+ | llvmlibc-inline-function-decl | Yes | +--------------------------------------------------------+--------------+ | llvmlibc-restrict-system-libc-headers | Yes | +--------------------------------------------------------+--------------+ | misc-confusable-identifiers | | +--------------------------------------------------------+--------------+ | misc-const-correctness | Yes | +--------------------------------------------------------+--------------+ | misc-coroutine-hostile-raii | | +--------------------------------------------------------+--------------+ | misc-definitions-in-headers | Yes | +--------------------------------------------------------+--------------+ | misc-header-include-cycle | | +--------------------------------------------------------+--------------+ | misc-include-cleaner | Yes | +--------------------------------------------------------+--------------+ | misc-misleading-bidirectional | | +--------------------------------------------------------+--------------+ | misc-misleading-identifier | | +--------------------------------------------------------+--------------+ | misc-misplaced-const | | +--------------------------------------------------------+--------------+ | misc-new-delete-overloads | | +--------------------------------------------------------+--------------+ | misc-no-recursion | | +--------------------------------------------------------+--------------+ | misc-non-copyable-objects | | +--------------------------------------------------------+--------------+ | misc-non-private-member-variables-in-classes | | +--------------------------------------------------------+--------------+ | misc-redundant-expression | Yes | +--------------------------------------------------------+--------------+ | misc-static-assert | Yes | +--------------------------------------------------------+--------------+ | misc-throw-by-value-catch-by-reference | | +--------------------------------------------------------+--------------+ | misc-unconventional-assign-operator | | +--------------------------------------------------------+--------------+ | misc-uniqueptr-reset-release | Yes | +--------------------------------------------------------+--------------+ | misc-unused-alias-decls | Yes | +--------------------------------------------------------+--------------+ | misc-unused-parameters | Yes | +--------------------------------------------------------+--------------+ | misc-unused-using-decls | Yes | +--------------------------------------------------------+--------------+ | misc-use-anonymous-namespace | | +--------------------------------------------------------+--------------+ | modernize-avoid-bind | Yes | +--------------------------------------------------------+--------------+ | modernize-avoid-c-arrays | | +--------------------------------------------------------+--------------+ | modernize-concat-nested-namespaces | Yes | +--------------------------------------------------------+--------------+ | modernize-deprecated-headers | Yes | +--------------------------------------------------------+--------------+ | modernize-deprecated-ios-base-aliases | Yes | +--------------------------------------------------------+--------------+ | modernize-loop-convert | Yes | +--------------------------------------------------------+--------------+ | modernize-macro-to-enum | Yes | +--------------------------------------------------------+--------------+ | modernize-make-shared | Yes | +--------------------------------------------------------+--------------+ | modernize-make-unique | Yes | +--------------------------------------------------------+--------------+ | modernize-pass-by-value | Yes | +--------------------------------------------------------+--------------+ | modernize-raw-string-literal | Yes | +--------------------------------------------------------+--------------+ | modernize-redundant-void-arg | Yes | +--------------------------------------------------------+--------------+ | modernize-replace-auto-ptr | Yes | +--------------------------------------------------------+--------------+ | modernize-replace-disallow-copy-and-assign-macro | Yes | +--------------------------------------------------------+--------------+ | modernize-replace-random-shuffle | Yes | +--------------------------------------------------------+--------------+ | modernize-return-braced-init-list | Yes | +--------------------------------------------------------+--------------+ | modernize-shrink-to-fit | Yes | +--------------------------------------------------------+--------------+ | modernize-type-traits | Yes | +--------------------------------------------------------+--------------+ | modernize-unary-static-assert | Yes | +--------------------------------------------------------+--------------+ | modernize-use-auto | Yes | +--------------------------------------------------------+--------------+ | modernize-use-bool-literals | Yes | +--------------------------------------------------------+--------------+ | modernize-use-constraints | Yes | +--------------------------------------------------------+--------------+ | modernize-use-default-member-init | Yes | +--------------------------------------------------------+--------------+ | modernize-use-emplace | Yes | +--------------------------------------------------------+--------------+ | modernize-use-equals-default | Yes | +--------------------------------------------------------+--------------+ | modernize-use-equals-delete | Yes | +--------------------------------------------------------+--------------+ | modernize-use-nodiscard | Yes | +--------------------------------------------------------+--------------+ | modernize-use-noexcept | Yes | +--------------------------------------------------------+--------------+ | modernize-use-nullptr | Yes | +--------------------------------------------------------+--------------+ | modernize-use-override | Yes | +--------------------------------------------------------+--------------+ | modernize-use-starts-ends-with | Yes | +--------------------------------------------------------+--------------+ | modernize-use-std-numbers | Yes | +--------------------------------------------------------+--------------+ | modernize-use-std-print | Yes | +--------------------------------------------------------+--------------+ | modernize-use-trailing-return-type | Yes | +--------------------------------------------------------+--------------+ | modernize-use-transparent-functors | Yes | +--------------------------------------------------------+--------------+ | modernize-use-uncaught-exceptions | Yes | +--------------------------------------------------------+--------------+ | modernize-use-using | Yes | +--------------------------------------------------------+--------------+ | mpi-buffer-deref | Yes | +--------------------------------------------------------+--------------+ | mpi-type-mismatch | Yes | +--------------------------------------------------------+--------------+ | objc-assert-equals | Yes | +--------------------------------------------------------+--------------+ | objc-avoid-nserror-init | | +--------------------------------------------------------+--------------+ | objc-dealloc-in-category | | +--------------------------------------------------------+--------------+ | objc-forbidden-subclassing | | +--------------------------------------------------------+--------------+ | objc-missing-hash | | +--------------------------------------------------------+--------------+ | objc-nsdate-formatter | | +--------------------------------------------------------+--------------+ | objc-nsinvocation-argument-lifetime | Yes | +--------------------------------------------------------+--------------+ | objc-property-declaration | Yes | +--------------------------------------------------------+--------------+ | objc-super-self | Yes | +--------------------------------------------------------+--------------+ | openmp-exception-escape | | +--------------------------------------------------------+--------------+ | openmp-use-default-none | | +--------------------------------------------------------+--------------+ | performance-avoid-endl | Yes | +--------------------------------------------------------+--------------+ | performance-enum-size | | +--------------------------------------------------------+--------------+ | performance-faster-string-find | Yes | +--------------------------------------------------------+--------------+ | performance-for-range-copy | Yes | +--------------------------------------------------------+--------------+ | performance-implicit-conversion-in-loop | | +--------------------------------------------------------+--------------+ | performance-inefficient-algorithm | Yes | +--------------------------------------------------------+--------------+ | performance-inefficient-string-concatenation | | +--------------------------------------------------------+--------------+ | performance-inefficient-vector-operation | Yes | +--------------------------------------------------------+--------------+ | performance-move-const-arg | Yes | +--------------------------------------------------------+--------------+ | performance-move-constructor-init | | +--------------------------------------------------------+--------------+ | performance-no-automatic-move | | +--------------------------------------------------------+--------------+ | performance-no-int-to-ptr | | +--------------------------------------------------------+--------------+ | performance-noexcept-destructor | Yes | +--------------------------------------------------------+--------------+ | performance-noexcept-move-constructor | Yes | +--------------------------------------------------------+--------------+ | performance-noexcept-swap | Yes | +--------------------------------------------------------+--------------+ | performance-trivially-destructible | Yes | +--------------------------------------------------------+--------------+ | performance-type-promotion-in-math-fn | Yes | +--------------------------------------------------------+--------------+ | performance-unnecessary-copy-initialization | Yes | +--------------------------------------------------------+--------------+ | performance-unnecessary-value-param | Yes | +--------------------------------------------------------+--------------+ | portability-restrict-system-includes | Yes | +--------------------------------------------------------+--------------+ | portability-simd-intrinsics | | +--------------------------------------------------------+--------------+ | portability-std-allocator-const | | +--------------------------------------------------------+--------------+ | readability-avoid-const-params-in-decls | Yes | +--------------------------------------------------------+--------------+ | readability-avoid-nested-conditional-operator | | +--------------------------------------------------------+--------------+ | readability-avoid-return-with-void-value | | +--------------------------------------------------------+--------------+ | readability-avoid-unconditional-preprocessor-if | | +--------------------------------------------------------+--------------+ | readability-braces-around-statements | Yes | +--------------------------------------------------------+--------------+ | readability-const-return-type | Yes | +--------------------------------------------------------+--------------+ | readability-container-contains | Yes | +--------------------------------------------------------+--------------+ | readability-container-data-pointer | Yes | +--------------------------------------------------------+--------------+ | readability-container-size-empty | Yes | +--------------------------------------------------------+--------------+ | readability-convert-member-functions-to-static | Yes | +--------------------------------------------------------+--------------+ | readability-delete-null-pointer | Yes | +--------------------------------------------------------+--------------+ | readability-duplicate-include | Yes | +--------------------------------------------------------+--------------+ | readability-else-after-return | Yes | +--------------------------------------------------------+--------------+ | readability-function-cognitive-complexity | | +--------------------------------------------------------+--------------+ | readability-function-size | | +--------------------------------------------------------+--------------+ | readability-identifier-length | | +--------------------------------------------------------+--------------+ | readability-identifier-naming | Yes | +--------------------------------------------------------+--------------+ | readability-implicit-bool-conversion | Yes | +--------------------------------------------------------+--------------+ | readability-inconsistent-declaration-parameter-name | Yes | +--------------------------------------------------------+--------------+ | readability-isolate-declaration | Yes | +--------------------------------------------------------+--------------+ | readability-magic-numbers | | +--------------------------------------------------------+--------------+ | readability-make-member-function-const | Yes | +--------------------------------------------------------+--------------+ | readability-misleading-indentation | | +--------------------------------------------------------+--------------+ | readability-misplaced-array-index | Yes | +--------------------------------------------------------+--------------+ | readability-named-parameter | Yes | +--------------------------------------------------------+--------------+ | readability-non-const-parameter | Yes | +--------------------------------------------------------+--------------+ | readability-operators-representation | Yes | +--------------------------------------------------------+--------------+ | readability-qualified-auto | Yes | +--------------------------------------------------------+--------------+ | readability-redundant-access-specifiers | Yes | +--------------------------------------------------------+--------------+ | readability-redundant-casting | Yes | +--------------------------------------------------------+--------------+ | readability-redundant-control-flow | Yes | +--------------------------------------------------------+--------------+ | readability-redundant-declaration | Yes | +--------------------------------------------------------+--------------+ | readability-redundant-function-ptr-dereference | Yes | +--------------------------------------------------------+--------------+ | readability-redundant-inline-specifier | Yes | +--------------------------------------------------------+--------------+ | readability-redundant-member-init | Yes | +--------------------------------------------------------+--------------+ | readability-redundant-preprocessor | | +--------------------------------------------------------+--------------+ | readability-redundant-smartptr-get | Yes | +--------------------------------------------------------+--------------+ | readability-redundant-string-cstr | Yes | +--------------------------------------------------------+--------------+ | readability-redundant-string-init | Yes | +--------------------------------------------------------+--------------+ | readability-reference-to-constructed-temporary | | +--------------------------------------------------------+--------------+ | readability-simplify-boolean-expr | Yes | +--------------------------------------------------------+--------------+ | readability-simplify-subscript-expr | Yes | +--------------------------------------------------------+--------------+ | readability-static-accessed-through-instance | Yes | +--------------------------------------------------------+--------------+ | readability-static-definition-in-anonymous-namespace | Yes | +--------------------------------------------------------+--------------+ | readability-string-compare | Yes | +--------------------------------------------------------+--------------+ | readability-suspicious-call-argument | | +--------------------------------------------------------+--------------+ | readability-uniqueptr-delete-release | Yes | +--------------------------------------------------------+--------------+ | readability-uppercase-literal-suffix | Yes | +--------------------------------------------------------+--------------+ | readability-use-anyofallof | | +--------------------------------------------------------+--------------+ | zircon-temporary-objects | | +--------------------------------------------------------+--------------+ Aliases.. +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | Name | Redirect | Offers fixes | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | bugprone-narrowing-conversions | cppcoreguidelines-narrowing-conversions | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | cert-con36-c | bugprone-spuriously-wake-up-functions | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | cert-con54-cpp | bugprone-spuriously-wake-up-functions | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | cert-dcl03-c | misc-static-assert | Yes | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | cert-dcl16-c | readability-uppercase-literal-suffix | Yes | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | cert-dcl37-c | bugprone-reserved-identifier | Yes | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | cert-dcl51-cpp | bugprone-reserved-identifier | Yes | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | cert-dcl54-cpp | misc-new-delete-overloads | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | cert-dcl59-cpp | google-build-namespaces | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | cert-err09-cpp | misc-throw-by-value-catch-by-reference | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | cert-err61-cpp | misc-throw-by-value-catch-by-reference | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | cert-exp42-c | bugprone-suspicious-memory-comparison | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | cert-fio38-c | misc-non-copyable-objects | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | cert-flp37-c | bugprone-suspicious-memory-comparison | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | cert-msc24-c | bugprone-unsafe-functions | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | cert-msc30-c | cert-msc50-cpp | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | cert-msc32-c | cert-msc51-cpp | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | cert-msc33-c | bugprone-unsafe-functions | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | cert-msc54-cpp | bugprone-signal-handler | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | cert-oop11-cpp | performance-move-constructor-init | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | cert-oop54-cpp | bugprone-unhandled-self-assignment | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | cert-pos44-c | bugprone-bad-signal-to-kill-thread | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | cert-pos47-c | concurrency-thread-canceltype-asynchronous | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | cert-sig30-c | bugprone-signal-handler | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | cert-str34-c | bugprone-signed-char-misuse | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | clang-analyzer-core.BitwiseShift | Clang Static Analyzer core.BitwiseShift | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | clang-analyzer-core.CallAndMessage | Clang Static Analyzer core.CallAndMessage | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | clang-analyzer-core.DivideZero | Clang Static Analyzer core.DivideZero | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | clang-analyzer-core.NonNullParamChecker | Clang Static Analyzer core.NonNullParam- | | | | Checker | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | clang-analyzer-core.NullDereference | Clang Static Analyzer core.NullDereference | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | clang-analyzer-core.StackAddressEscape | Clang Static Analyzer core.StackAddress- | | | | Escape | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | clang-analyzer-core.UndefinedBinaryOperatorResult | Clang Static Analyzer core.UndefinedBina- | | | | ryOperatorResult | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | clang-analyzer-core.VLASize | Clang Static Analyzer core.VLASize | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | clang-analyzer-core.uninitialized.ArraySubscript | Clang Static Analyzer core.uninitial- | | | | ized.ArraySubscript | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | clang-analyzer-core.uninitialized.Assign | Clang Static Analyzer core.uninitial- | | | | ized.Assign | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | clang-analyzer-core.uninitialized.Branch | Clang Static Analyzer core.uninitial- | | | | ized.Branch | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | clang-analyzer-core.uninitialized.CapturedBlockVariable | Clang Static Analyzer core.uninitial- | | | | ized.CapturedBlockVariable | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | clang-analyzer-core.uninitialized.NewArraySize | Clang Static Analyzer core.uninitial- | | | | ized.NewArraySize | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | clang-analyzer-core.uninitialized.UndefReturn | Clang Static Analyzer core.uninitial- | | | | ized.UndefReturn | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | clang-analyzer-cplusplus.InnerPointer | Clang Static Analyzer cplusplus.Inner- | | | | Pointer | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | clang-analyzer-cplusplus.Move | Clang Static Analyzer cplusplus.Move | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | clang-analyzer-cplusplus.NewDelete | Clang Static Analyzer cplusplus.NewDelete | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | clang-analyzer-cplusplus.NewDeleteLeaks | Clang Static Analyzer cplusplus.NewDelete- | | | | Leaks | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | clang-analyzer-cplusplus.PlacementNew | Clang Static Analyzer cplusplus.Placement- | | | | New | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | clang-analyzer-cplusplus.PureVirtualCall | Clang Static Analyzer cplusplus.PureVirtu- | | | | alCall | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | clang-analyzer-cplusplus.StringChecker | Clang Static Analyzer cplus- | | | | plus.StringChecker | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | clang-analyzer-deadcode.DeadStores | Clang Static Analyzer deadcode.DeadStores | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | clang-analyzer-fuchsia.HandleChecker | Clang Static Analyzer fuchsia.Han- | | | | dleChecker | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | clang-analyzer-nullability.NullPassedToNonnull | Clang Static Analyzer nullability.Null- | | | | PassedToNonnull | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | clang-analyzer-nullability.NullReturnedFromNonnull | Clang Static Analyzer nullability.NullRe- | | | | turnedFromNonnull | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | clang-analyzer-nullability.NullableDereferenced | Clang Static Analyzer nullability.Nul- | | | | lableDereferenced | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | clang-analyzer-nullability.NullablePassedToNonnull | Clang Static Analyzer nullability.Nul- | | | | lablePassedToNonnull | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | clang-analyzer-nullability.NullableReturnedFromNonnull | Clang Static Analyzer nullability.Nul- | | | | lableReturnedFromNonnull | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | clang-analyzer-optin.core.EnumCastOutOfRange | Clang Static Analyzer optin.core.Enum- | | | | CastOutOfRange | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | clang-analyzer-optin.cplusplus.UninitializedObject | Clang Static Analyzer optin.cplus- | | | | plus.UninitializedObject | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | clang-analyzer-optin.cplusplus.VirtualCall | Clang Static Analyzer optin.cplusplus.Vir- | | | | tualCall | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | clang-analyzer-optin.mpi.MPI-Checker | Clang Static Analyzer | | | | optin.mpi.MPI-Checker | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | clang-analyzer-optin.osx.OSObjectCStyleCast | Clang Static Analyzer optin.osx.OSObjectC- | | | | StyleCast | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | clang-analyzer-optin.osx.cocoa.localizability.EmptyLocalizationContextChecker | Clang Static Analyzer optin.osx.cocoa.lo- | | | | calizability.EmptyLocalizationCon- | | | | textChecker | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | clang-analyzer-optin.osx.cocoa.localizability.NonLocalizedStringChecker | Clang Static Analyzer optin.osx.cocoa.lo- | | | | calizability.NonLocalizedStringChecker | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | clang-analyzer-optin.performance.GCDAntipattern | Clang Static Analyzer optin.perfor- | | | | mance.GCDAntipattern | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | clang-analyzer-optin.performance.Padding | Clang Static Analyzer optin.perfor- | | | | mance.Padding | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | clang-analyzer-optin.portability.UnixAPI | Clang Static Analyzer optin.portabil- | | | | ity.UnixAPI | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | clang-analyzer-osx.API | Clang Static Analyzer osx.API | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | clang-analyzer-osx.MIG | Clang Static Analyzer osx.MIG | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | clang-analyzer-osx.NumberObjectConversion | Clang Static Analyzer osx.NumberObjectCon- | | | | version | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | clang-analyzer-osx.OSObjectRetainCount | Clang Static Analyzer osx.OSObjectRetain- | | | | Count | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | clang-analyzer-osx.ObjCProperty | Clang Static Analyzer osx.ObjCProperty | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | clang-analyzer-osx.SecKeychainAPI | Clang Static Analyzer osx.SecKeychainAPI | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | clang-analyzer-osx.cocoa.AtSync | Clang Static Analyzer osx.cocoa.AtSync | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | clang-analyzer-osx.cocoa.AutoreleaseWrite | Clang Static Analyzer osx.cocoa.Autore- | | | | leaseWrite | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | clang-analyzer-osx.cocoa.ClassRelease | Clang Static Analyzer osx.cocoa.ClassRe- | | | | lease | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | clang-analyzer-osx.cocoa.Dealloc | Clang Static Analyzer osx.cocoa.Dealloc | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | clang-analyzer-osx.cocoa.IncompatibleMethodTypes | Clang Static Analyzer osx.cocoa.Incompati- | | | | bleMethodTypes | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | clang-analyzer-osx.cocoa.Loops | Clang Static Analyzer osx.cocoa.Loops | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | clang-analyzer-osx.cocoa.MissingSuperCall | Clang Static Analyzer osx.cocoa.MissingSu- | | | | perCall | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | clang-analyzer-osx.cocoa.NSAutoreleasePool | Clang Static Analyzer osx.cocoa.NSAutore- | | | | leasePool | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | clang-analyzer-osx.cocoa.NSError | Clang Static Analyzer osx.cocoa.NSError | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | clang-analyzer-osx.cocoa.NilArg | Clang Static Analyzer osx.cocoa.NilArg | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | clang-analyzer-osx.cocoa.NonNilReturnValue | Clang Static Analyzer osx.cocoa.NonNilRe- | | | | turnValue | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | clang-analyzer-osx.cocoa.ObjCGenerics | Clang Static Analyzer osx.cocoa.ObjCGener- | | | | ics | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | clang-analyzer-osx.cocoa.RetainCount | Clang Static Analyzer osx.cocoa.Retain- | | | | Count | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | clang-analyzer-osx.cocoa.RunLoopAutoreleaseLeak | Clang Static Analyzer osx.cocoa.RunLoopAu- | | | | toreleaseLeak | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | clang-analyzer-osx.cocoa.SelfInit | Clang Static Analyzer osx.cocoa.SelfInit | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | clang-analyzer-osx.cocoa.SuperDealloc | Clang Static Analyzer osx.cocoa.SuperDeal- | | | | loc | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | clang-analyzer-osx.cocoa.UnusedIvars | Clang Static Analyzer osx.cocoa.UnusedI- | | | | vars | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | clang-analyzer-osx.cocoa.VariadicMethodTypes | Clang Static Analyzer osx.cocoa.Vari- | | | | adicMethodTypes | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | clang-analyzer-osx.coreFoundation.CFError | Clang Static Analyzer osx.coreFounda- | | | | tion.CFError | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | clang-analyzer-osx.coreFoundation.CFNumber | Clang Static Analyzer osx.coreFounda- | | | | tion.CFNumber | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | clang-analyzer-osx.coreFoundation.CFRetainRelease | Clang Static Analyzer osx.coreFounda- | | | | tion.CFRetainRelease | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | clang-analyzer-osx.coreFoundation.containers.OutOfBounds | Clang Static Analyzer osx.coreFounda- | | | | tion.containers.OutOfBounds | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | clang-analyzer-osx.coreFoundation.containers.PointerSizedValues | Clang Static Analyzer osx.coreFounda- | | | | tion.containers.PointerSizedValues | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | clang-analyzer-security.FloatLoopCounter | Clang Static Analyzer security.FloatLoop- | | | | Counter | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | clang-analyzer-security.cert.env.InvalidPtr | Clang Static Analyzer secu- | | | | rity.cert.env.InvalidPtr | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling | Clang Static Analyzer security.inse- | | | | cureAPI.DeprecatedOrUnsafeBufferHandling | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | clang-analyzer-security.insecureAPI.UncheckedReturn | Clang Static Analyzer security.inse- | | | | cureAPI.UncheckedReturn | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | clang-analyzer-security.insecureAPI.bcmp | Clang Static Analyzer security.inse- | | | | cureAPI.bcmp | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | clang-analyzer-security.insecureAPI.bcopy | Clang Static Analyzer security.inse- | | | | cureAPI.bcopy | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | clang-analyzer-security.insecureAPI.bzero | Clang Static Analyzer security.inse- | | | | cureAPI.bzero | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | clang-analyzer-security.insecureAPI.decodeValueOfObjCType | Clang Static Analyzer security.inse- | | | | cureAPI.decodeValueOfObjCType | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | clang-analyzer-security.insecureAPI.getpw | Clang Static Analyzer security.inse- | | | | cureAPI.getpw | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | clang-analyzer-security.insecureAPI.gets | Clang Static Analyzer security.inse- | | | | cureAPI.gets | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | clang-analyzer-security.insecureAPI.mkstemp | Clang Static Analyzer security.inse- | | | | cureAPI.mkstemp | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | clang-analyzer-security.insecureAPI.mktemp | Clang Static Analyzer security.inse- | | | | cureAPI.mktemp | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | clang-analyzer-security.insecureAPI.rand | Clang Static Analyzer security.inse- | | | | cureAPI.rand | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | clang-analyzer-security.insecureAPI.strcpy | Clang Static Analyzer security.inse- | | | | cureAPI.strcpy | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | clang-analyzer-security.insecureAPI.vfork | Clang Static Analyzer security.inse- | | | | cureAPI.vfork | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | clang-analyzer-unix.API | Clang Static Analyzer unix.API | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | clang-analyzer-unix.Errno | Clang Static Analyzer unix.Errno | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | clang-analyzer-unix.Malloc | Clang Static Analyzer unix.Malloc | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | clang-analyzer-unix.MallocSizeof | Clang Static Analyzer unix.MallocSizeof | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | clang-analyzer-unix.MismatchedDeallocator | Clang Static Analyzer unix.MismatchedDeal- | | | | locator | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | clang-analyzer-unix.StdCLibraryFunctions | Clang Static Analyzer unix.StdCLibrary- | | | | Functions | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | clang-analyzer-unix.Vfork | Clang Static Analyzer unix.Vfork | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | clang-analyzer-unix.cstring.BadSizeArg | Clang Static Analyzer unix.cstring.Bad- | | | | SizeArg | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | clang-analyzer-unix.cstring.NullArg | Clang Static Analyzer unix.cstring.NullArg | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | clang-analyzer-valist.CopyToSelf | Clang Static Analyzer valist.CopyToSelf | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | clang-analyzer-valist.Uninitialized | Clang Static Analyzer valist.Uninitialized | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | clang-analyzer-valist.Unterminated | Clang Static Analyzer valist.Unterminated | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | clang-analyzer-webkit.NoUncountedMemberChecker | Clang Static Analyzer webkit.NoUncounted- | | | | MemberChecker | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | clang-analyzer-webkit.RefCntblBaseVirtualDtor | Clang Static Analyzer webkit.RefCntblBase- | | | | VirtualDtor | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | clang-analyzer-webkit.UncountedLambdaCapturesChecker | Clang Static Analyzer webkit.Uncounted- | | | | LambdaCapturesChecker | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | cppcoreguidelines-avoid-c-arrays | modernize-avoid-c-arrays | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | cppcoreguidelines-avoid-magic-numbers | readability-magic-numbers | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | cppcoreguidelines-c-copy-assignment-signature | misc-unconventional-assign-operator | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | cppcoreguidelines-explicit-virtual-functions | modernize-use-override | Yes | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | cppcoreguidelines-macro-to-enum | modernize-macro-to-enum | Yes | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | cppcoreguidelines-noexcept-destructor | performance-noexcept-destructor | Yes | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | cppcoreguidelines-noexcept-move-operations | performance-noexcept-move-constructor | Yes | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | cppcoreguidelines-noexcept-swap | performance-noexcept-swap | Yes | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | cppcoreguidelines-non-private-member-variables-in-classes | misc-non-private-member-variables-in-classes | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | cppcoreguidelines-use-default-member-init | modernize-use-default-member-init | Yes | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | fuchsia-header-anon-namespaces | google-build-namespaces | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | google-readability-braces-around-statements | readability-braces-around-statements | Yes | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | google-readability-function-size | readability-function-size | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | google-readability-namespace-comments | llvm-namespace-comment | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | hicpp-avoid-c-arrays | modernize-avoid-c-arrays | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | hicpp-avoid-goto | cppcoreguidelines-avoid-goto | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | hicpp-braces-around-statements | readability-braces-around-statements | Yes | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | hicpp-deprecated-headers | modernize-deprecated-headers | Yes | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | hicpp-explicit-conversions | google-explicit-constructor | Yes | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | hicpp-function-size | readability-function-size | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | hicpp-invalid-access-moved | bugprone-use-after-move | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | hicpp-member-init | cppcoreguidelines-pro-type-member-init | Yes | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | hicpp-move-const-arg | performance-move-const-arg | Yes | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | hicpp-named-parameter | readability-named-parameter | Yes | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | hicpp-new-delete-operators | misc-new-delete-overloads | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | hicpp-no-array-decay | cppcoreguidelines-pro-bounds-array-to-pointer-decay | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | hicpp-no-malloc | cppcoreguidelines-no-malloc | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | hicpp-noexcept-move | performance-noexcept-move-constructor | Yes | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | hicpp-special-member-functions | cppcoreguidelines-special-member-functions | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | hicpp-static-assert | misc-static-assert | Yes | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | hicpp-undelegated-constructor | bugprone-undelegated-constructor | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | hicpp-uppercase-literal-suffix | readability-uppercase-literal-suffix | Yes | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | hicpp-use-auto | modernize-use-auto | Yes | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | hicpp-use-emplace | modernize-use-emplace | Yes | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | hicpp-use-equals-default | modernize-use-equals-default | Yes | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | hicpp-use-equals-delete | modernize-use-equals-delete | Yes | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | hicpp-use-noexcept | modernize-use-noexcept | Yes | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | hicpp-use-nullptr | modernize-use-nullptr | Yes | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | hicpp-use-override | modernize-use-override | Yes | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | hicpp-vararg | cppcoreguidelines-pro-type-vararg | | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | llvm-else-after-return | readability-else-after-return | Yes | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ | llvm-qualified-auto | readability-qualified-auto | Yes | +-------------------------------------------------------------------------------+-----------------------------------------------------+--------------+ Clang-tidy IDE/Editor Integrations Apart from being a standalone tool, clang-tidy is integrated into vari- ous IDEs, code analyzers, and editors. We recommend using clangd which integrates clang-tidy and is available in most major editors through plugins (Vim, Emacs, Visual Studio Code, Sublime Text and more). The following table shows the most well-known clang-tidy integrations in detail. +-------------+------------+-------------+-------------+-------------+------------+ | | Feature | | | | | +-------------+------------+-------------+-------------+-------------+------------+ | Tool | On-the-fly | Check list | Options to | Configura- | Custom | | | inspection | configura- | checks | tion via | clang-tidy | | | | tion (GUI) | (GUI) | .clang-tidy | binary | | | | | | files | | +-------------+------------+-------------+-------------+-------------+------------+ | A.L.E. for | + | - | - | - | + | | Vim | | | | | | +-------------+------------+-------------+-------------+-------------+------------+ | Clang Power | - | + | - | + | - | | Tools for | | | | | | | Visual Stu- | | | | | | | dio | | | | | | +-------------+------------+-------------+-------------+-------------+------------+ | Clangd | + | - | - | + | - | +-------------+------------+-------------+-------------+-------------+------------+ | CLion IDE | + | + | + | + | + | +-------------+------------+-------------+-------------+-------------+------------+ | CodeChecker | - | - | - | - | + | +-------------+------------+-------------+-------------+-------------+------------+ | CPPCheck | - | - | - | - | - | +-------------+------------+-------------+-------------+-------------+------------+ | CPPDepend | - | - | - | - | - | +-------------+------------+-------------+-------------+-------------+------------+ | Flycheck | + | - | - | + | + | | for Emacs | | | | | | +-------------+------------+-------------+-------------+-------------+------------+ | KDevelop | - | + | + | + | + | | IDE | | | | | | +-------------+------------+-------------+-------------+-------------+------------+ | Qt Creator | + | + | - | + | + | | IDE | | | | | | +-------------+------------+-------------+-------------+-------------+------------+ | ReSharper | + | + | - | + | + | | C++ for Vi- | | | | | | | sual Studio | | | | | | +-------------+------------+-------------+-------------+-------------+------------+ | Syntastic | + | - | - | - | + | | for Vim | | | | | | +-------------+------------+-------------+-------------+-------------+------------+ | Visual As- | + | + | - | - | - | | sist for | | | | | | | Visual Stu- | | | | | | | dio | | | | | | +-------------+------------+-------------+-------------+-------------+------------+ IDEs CLion 2017.2 and later integrates clang-tidy as an extension to the built-in code analyzer. Starting from 2018.2 EAP, CLion allows using clang-tidy via Clangd. Inspections and applicable quick-fixes are per- formed on the fly, and checks can be configured in standard command line format. In this integration, you can switch to the clang-tidy bi- nary different from the bundled one, pass the configuration in .clang-tidy files instead of using the IDE settings, and configure op- tions for particular checks. KDevelop with the kdev-clang-tidy plugin, starting from version 5.1, performs static analysis using clang-tidy. The plugin launches the clang-tidy binary from the specified location and parses its output to provide a list of issues. QtCreator 4.6 integrates clang-tidy warnings into the editor diagnos- tics under the Clang Code Model. To employ clang-tidy inspection in Qt- Creator, you need to create a copy of one of the presets and choose the checks to be performed. Since QtCreator 4.7 project-wide analysis is possible with the Clang Tools analyzer. MS Visual Studio can integrate clang-tidy by means of three different tools. The ReSharper C++ extension, version 2017.3 and later, provides seamless clang-tidy integration: checks and quick-fixes run alongside native inspections. Apart from that, ReSharper C++ incorporates clang-tidy as a separate step of its code clean-up process. Visual As- sist build 2210 includes a subset of clang-tidy checklist to inspect the code as you edit. Another way to bring clang-tidy functionality to Visual Studio is the Clang Power Tools plugin, which includes most of the clang-tidy checks and runs them during compilation or as a separate step of code analysis. Editors Emacs24, when expanded with the Flycheck plugin, incorporates the clang-tidy inspection into the syntax analyzer. For Vim, you can use Syntastic, which includes clang-tidy, or A.L.E., a lint engine that ap- plies clang-tidy along with other linters. Analyzers clang-tidy is integrated in CPPDepend starting from version 2018.1 and CPPCheck 1.82. CPPCheck integration lets you import Visual Studio solu- tions and run the clang-tidy inspection on them. The CodeChecker appli- cation of version 5.3 or later, which also comes as a plugin for Eclipse, supports clang-tidy as a static analysis instrument and allows to use a custom clang-tidy binary. Getting Involved clang-tidy has several own checks and can run Clang static analyzer checks, but its power is in the ability to easily write custom checks. Checks are organized in modules, which can be linked into clang-tidy with minimal or no code changes in clang-tidy. Checks can plug into the analysis on the preprocessor level using PPCallbacks or on the AST level using AST Matchers. When an error is found, checks can report them in a way similar to how Clang diagnostics work. A fix-it hint can be attached to a diagnostic message. The interface provided by clang-tidy makes it easy to write useful and precise checks in just a few lines of code. If you have an idea for a good check, the rest of this document explains how to do this. There are a few tools particularly useful when developing clang-tidy checks: • add_new_check.py is a script to automate the process of adding a new check, it will create the check, update the CMake file and create a test; • rename_check.py does what the script name suggests, renames an existing check; • pp-trace logs method calls on PPCallbacks for a source file and is invaluable in understanding the preprocessor mechanism; • clang-query is invaluable for interactive prototyping of AST matchers and exploration of the Clang AST; • clang-check with the -ast-dump (and optionally -ast-dump-fil- ter) provides a convenient way to dump AST of a C++ program. If CMake is configured with CLANG_TIDY_ENABLE_STATIC_ANALYZER=NO, clang-tidy will not be built with support for the clang-analyzer-* checks or the mpi-* checks. Choosing the Right Place for your Check If you have an idea of a check, you should decide whether it should be implemented as a: • Clang diagnostic: if the check is generic enough, targets code pat- terns that most probably are bugs (rather than style or readability issues), can be implemented effectively and with extremely low false positive rate, it may make a good Clang diagnostic. • Clang static analyzer check: if the check requires some sort of con- trol flow analysis, it should probably be implemented as a static an- alyzer check. • clang-tidy check is a good choice for linter-style checks, checks that are related to a certain coding style, checks that address code readability, etc. Preparing your Workspace If you are new to LLVM development, you should read the Getting Started with the LLVM System, Using Clang Tools and How To Setup Clang Tooling For LLVM documents to check out and build LLVM, Clang and Clang Extra Tools with CMake. Once you are done, change to the llvm/clang-tools-extra directory, and let's start! When you configure the CMake build, make sure that you enable the clang and clang-tools-extra projects to build clang-tidy. Because your new check will have associated documentation, you will also want to install Sphinx and enable it in the CMake configuration. To save build time of the core Clang libraries you may want to only enable the X86 target in the CMake configuration. The Directory Structure clang-tidy source code resides in the llvm/clang-tools-extra directory and is structured as follows: clang-tidy/ # Clang-tidy core. |-- ClangTidy.h # Interfaces for users. |-- ClangTidyCheck.h # Interfaces for checks. |-- ClangTidyModule.h # Interface for clang-tidy modules. |-- ClangTidyModuleRegistry.h # Interface for registering of modules. ... |-- google/ # Google clang-tidy module. |-+ |-- GoogleTidyModule.cpp |-- GoogleTidyModule.h ... |-- llvm/ # LLVM clang-tidy module. |-+ |-- LLVMTidyModule.cpp |-- LLVMTidyModule.h ... |-- objc/ # Objective-C clang-tidy module. |-+ |-- ObjCTidyModule.cpp |-- ObjCTidyModule.h ... |-- tool/ # Sources of the clang-tidy binary. ... test/clang-tidy/ # Integration tests. ... unittests/clang-tidy/ # Unit tests. |-- ClangTidyTest.h |-- GoogleModuleTest.cpp |-- LLVMModuleTest.cpp |-- ObjCModuleTest.cpp ... Writing a clang-tidy Check So you have an idea of a useful check for clang-tidy. First, if you're not familiar with LLVM development, read through the Getting Started with LLVM document for instructions on setting up your workflow and the LLVM Coding Standards document to familiarize yourself with the coding style used in the project. For code reviews we mostly use LLVM Phabricator. Next, you need to decide which module the check belongs to. Modules are located in subdirectories of clang-tidy/ and contain checks targeting a certain aspect of code quality (performance, readability, etc.), cer- tain coding style or standard (Google, LLVM, CERT, etc.) or a widely used API (e.g. MPI). Their names are the same as the user-facing check group names described above. After choosing the module and the name for the check, run the clang-tidy/add_new_check.py script to create the skeleton of the check and plug it to clang-tidy. It's the recommended way of adding new checks. If we want to create a readability-awesome-function-names, we would run: $ clang-tidy/add_new_check.py readability awesome-function-names The add_new_check.py script will: • create the class for your check inside the specified module's directory and register it in the module and in the build sys- tem; • create a lit test file in the test/clang-tidy/ directory; • create a documentation file and include it into the docs/clang-tidy/checks/list.rst. Let's see in more detail at the check class definition: ... #include "../ClangTidyCheck.h" namespace clang { namespace tidy { namespace readability { ... class AwesomeFunctionNamesCheck : public ClangTidyCheck { public: AwesomeFunctionNamesCheck(StringRef Name, ClangTidyContext *Context) : ClangTidyCheck(Name, Context) {} void registerMatchers(ast_matchers::MatchFinder *Finder) override; void check(const ast_matchers::MatchFinder::MatchResult &Result) override; }; } // namespace readability } // namespace tidy } // namespace clang ... Constructor of the check receives the Name and Context parameters, and must forward them to the ClangTidyCheck constructor. In our case the check needs to operate on the AST level and it over- rides the registerMatchers and check methods. If we wanted to analyze code on the preprocessor level, we'd need instead to override the reg- isterPPCallbacks method. In the registerMatchers method we create an AST Matcher (see AST Match- ers for more information) that will find the pattern in the AST that we want to inspect. The results of the matching are passed to the check method, which can further inspect them and report diagnostics. using namespace ast_matchers; void AwesomeFunctionNamesCheck::registerMatchers(MatchFinder *Finder) { Finder->addMatcher(functionDecl().bind("x"), this); } void AwesomeFunctionNamesCheck::check(const MatchFinder::MatchResult &Result) { const auto *MatchedDecl = Result.Nodes.getNodeAs<FunctionDecl>("x"); if (!MatchedDecl->getIdentifier() || MatchedDecl->getName().startswith("awesome_")) return; diag(MatchedDecl->getLocation(), "function %0 is insufficiently awesome") << MatchedDecl << FixItHint::CreateInsertion(MatchedDecl->getLocation(), "awesome_"); } (If you want to see an example of a useful check, look at clang-tidy/google/ExplicitConstructorCheck.h and clang-tidy/google/ExplicitConstructorCheck.cpp). If you need to interact with macros or preprocessor directives, you will want to override the method registerPPCallbacks. The add_new_check.py script does not generate an override for this method in the starting point for your new check. If your check applies only under a specific set of language options, be sure to override the method isLanguageVersionSupported to reflect that. Check development tips Writing your first check can be a daunting task, particularly if you are unfamiliar with the LLVM and Clang code bases. Here are some sug- gestions for orienting yourself in the codebase and working on your check incrementally. Guide to useful documentation Many of the support classes created for LLVM are used by Clang, such as StringRef and SmallVector. These and other commonly used classes are described in the Important and useful LLVM APIs and Picking the Right Data Structure for the Task sections of the LLVM Programmer's Manual. You don't need to memorize all the details of these classes; the gener- ated doxygen documentation has everything if you need it. In the header LLVM/ADT/STLExtras.h you'll find useful versions of the STL al- gorithms that operate on LLVM containers, such as llvm::all_of. Clang is implemented on top of LLVM and introduces its own set of classes that you will interact with while writing your check. When a check issues diagnostics and fix-its, these are associated with loca- tions in the source code. Source code locations, source files, ranges of source locations and the SourceManager class provide the mechanisms for describing such locations. These and other topics are described in the "Clang" CFE Internals Manual. Whereas the doxygen generated docu- mentation serves as a reference to the internals of Clang, this docu- ment serves as a guide to other developers. Topics in that manual of interest to a check developer are: • The Clang "Basic" Library for information about diagnostics, fix-it hints and source locations. • The Lexer and Preprocessor Library for information about tokens, lex- ing (transforming characters into tokens) and the preprocessor. • The AST Library for information about how C++ source statements are represented as an abstract syntax tree (AST). Most checks will interact with C++ source code via the AST. Some checks will interact with the preprocessor. The input source file is lexed and preprocessed and then parsed into the AST. Once the AST is fully constructed, the check is run by applying the check's registered AST matchers against the AST and invoking the check with the set of matched nodes from the AST. Monitoring the actions of the preprocessor is detached from the AST construction, but a check can collect informa- tion during preprocessing for later use by the check when nodes are matched by the AST. Every syntactic (and sometimes semantic) element of the C++ source code is represented by different classes in the AST. You select the por- tions of the AST you're interested in by composing AST matcher func- tions. You will want to study carefully the AST Matcher Reference to understand the relationship between the different matcher functions. Using the Transformer library The Transformer library allows you to write a check that transforms source code by expressing the transformation as a RewriteRule. The Transformer library provides functions for composing edits to source code to create rewrite rules. Unless you need to perform low-level source location manipulation, you may want to consider writing your check with the Transformer library. The Clang Transformer Tutorial de- scribes the Transformer library in detail. To use the Transformer library, make the following changes to the code generated by the add_new_check.py script: • Include ../utils/TransformerClangTidyCheck.h instead of ../ClangTidy- Check.h • Change the base class of your check from ClangTidyCheck to Trans- formerClangTidyCheck • Delete the override of the registerMatchers and check methods in your check class. • Write a function that creates the RewriteRule for your check. • Call the function in your check's constructor to pass the rewrite rule to TransformerClangTidyCheck's constructor. Developing your check incrementally The best way to develop your check is to start with the simple test cases and increase complexity incrementally. The test file created by the add_new_check.py script is a starting point for your test cases. A rough outline of the process looks like this: • Write a test case for your check. • Prototype matchers on the test file using clang-query. • Capture the working matchers in the registerMatchers method. • Issue the necessary diagnostics and fix-its in the check method. • Add the necessary CHECK-MESSAGES and CHECK-FIXES annotations to your test case to validate the diagnostics and fix-its. • Build the target check-clang-tool to confirm the test passes. • Repeat the process until all aspects of your check are covered by tests. The quickest way to prototype your matcher is to use clang-query to in- teractively build up your matcher. For complicated matchers, build up a matching expression incrementally and use clang-query's let command to save named matching expressions to simplify your matcher. Just like breaking up a huge function into smaller chunks with intention-reveal- ing names can help you understand a complex algorithm, breaking up a matcher into smaller matchers with intention-revealing names can help you understand a complicated matcher. Once you have a working matcher, the C++ API will be virtually identical to your interactively con- structed matcher. You can use local variables to preserve your inten- tion-revealing names that you applied to nested matchers. Creating private matchers Sometimes you want to match a specific aspect of the AST that isn't provided by the existing AST matchers. You can create your own private matcher using the same infrastructure as the public matchers. A pri- vate matcher can simplify the processing in your check method by elimi- nating complex hand-crafted AST traversal of the matched nodes. Using the private matcher allows you to select the desired portions of the AST directly in the matcher and refer to it by a bound name in the check method. Unit testing helper code Private custom matchers are a good example of auxiliary support code for your check that can be tested with a unit test. It will be easier to test your matchers or other support classes by writing a unit test than by writing a FileCheck integration test. The ASTMatchersTests target contains unit tests for the public AST matcher classes and is a good source of testing idioms for matchers. You can build the Clang-tidy unit tests by building the ClangTidyTests target. Test targets in LLVM and Clang are excluded from the "build all" style action of IDE-based CMake generators, so you need to explic- itly build the target for the unit tests to be built. Making your check robust Once you've covered your check with the basic "happy path" scenarios, you'll want to torture your check with as many edge cases as you can cover in order to ensure your check is robust. Running your check on a large code base, such as Clang/LLVM, is a good way to catch things you forgot to account for in your matchers. However, the LLVM code base may be insufficient for testing purposes as it was developed against a particular set of coding styles and quality measures. The larger the corpus of code the check is tested against, the higher confidence the community will have in the check's efficacy and false positive rate. Some suggestions to ensure your check is robust: • Create header files that contain code matched by your check. • Validate that fix-its are properly applied to test header files with clang-tidy. You will need to perform this test manually until auto- mated support for checking messages and fix-its is added to the check_clang_tidy.py script. • Define macros that contain code matched by your check. • Define template classes that contain code matched by your check. • Define template specializations that contain code matched by your check. • Test your check under both Windows and Linux environments. • Watch out for high false positive rates. Ideally, a check would have no false positives, but given that matching against an AST is not control- or data flow- sensitive, a number of false positives are ex- pected. The higher the false positive rate, the less likely the check will be adopted in practice. Mechanisms should be put in place to help the user manage false positives. • There are two primary mechanisms for managing false positives: sup- porting a code pattern which allows the programmer to silence the di- agnostic in an ad hoc manner and check configuration options to con- trol the behavior of the check. • Consider supporting a code pattern to allow the programmer to silence the diagnostic whenever such a code pattern can clearly express the programmer's intent. For example, allowing an explicit cast to void to silence an unused variable diagnostic. • Consider adding check configuration options to allow the user to opt into more aggressive checking behavior without burdening users for the common high-confidence cases. Documenting your check The add_new_check.py script creates entries in the release notes, the list of checks and a new file for the check documentation itself. It is recommended that you have a concise summation of what your check does in a single sentence that is repeated in the release notes, as the first sentence in the doxygen comments in the header file for your check class and as the first sentence of the check documentation. Avoid the phrase "this check" in your check summation and check docu- mentation. If your check relates to a published coding guideline (C++ Core Guide- lines, MISRA, etc.) or style guide, provide links to the relevant guideline or style guide sections in your check documentation. Provide enough examples of the diagnostics and fix-its provided by the check so that a user can easily understand what will happen to their code when the check is run. If there are exceptions or limitations to your check, document them thoroughly. This will help users understand the scope of the diagnostics and fix-its provided by the check. Building the target docs-clang-tools-html will run the Sphinx documen- tation generator and create documentation HTML files in the tools/clang/tools/extra/docs/html directory in your build tree. Make sure that your check is correctly shown in the release notes and the list of checks. Make sure that the formatting and structure of your check's documentation looks correct. Registering your Check (The add_new_check.py script takes care of registering the check in an existing module. If you want to create a new module or know the de- tails, read on.) The check should be registered in the corresponding module with a dis- tinct name: class MyModule : public ClangTidyModule { public: void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override { CheckFactories.registerCheck<ExplicitConstructorCheck>( "my-explicit-constructor"); } }; Now we need to register the module in the ClangTidyModuleRegistry using a statically initialized variable: static ClangTidyModuleRegistry::Add<MyModule> X("my-module", "Adds my lint checks."); When using LLVM build system, we need to use the following hack to en- sure the module is linked into the clang-tidy binary: Add this near the ClangTidyModuleRegistry::Add<MyModule> variable: // This anchor is used to force the linker to link in the generated object file // and thus register the MyModule. volatile int MyModuleAnchorSource = 0; And this to the main translation unit of the clang-tidy binary (or the binary you link the clang-tidy library in) clang-tidy/ClangTidy- ForceLinker.h: // This anchor is used to force the linker to link the MyModule. extern volatile int MyModuleAnchorSource; static int MyModuleAnchorDestination = MyModuleAnchorSource; Configuring Checks If a check needs configuration options, it can access check-specific options using the Options.get<Type>("SomeOption", DefaultValue) call in the check constructor. In this case the check should also override the ClangTidyCheck::storeOptions method to make the options provided by the check discoverable. This method lets clang-tidy know which options the check implements and what the current values are (e.g. for the -dump-config command line option). class MyCheck : public ClangTidyCheck { const unsigned SomeOption1; const std::string SomeOption2; public: MyCheck(StringRef Name, ClangTidyContext *Context) : ClangTidyCheck(Name, Context), SomeOption(Options.get("SomeOption1", -1U)), SomeOption(Options.get("SomeOption2", "some default")) {} void storeOptions(ClangTidyOptions::OptionMap &Opts) override { Options.store(Opts, "SomeOption1", SomeOption1); Options.store(Opts, "SomeOption2", SomeOption2); } ... Assuming the check is registered with the name "my-check", the option can then be set in a .clang-tidy file in the following way: CheckOptions: my-check.SomeOption1: 123 my-check.SomeOption2: 'some other value' If you need to specify check options on a command line, you can use the inline YAML format: $ clang-tidy -config="{CheckOptions: {a: b, x: y}}" ... Testing Checks To run tests for clang-tidy, build the check-clang-tools target. For instance, if you configured your CMake build with the ninja project generator, use the command: $ ninja check-clang-tools clang-tidy checks can be tested using either unit tests or lit tests. Unit tests may be more convenient to test complex replacements with strict checks. Lit tests allow using partial text matching and regular expressions which makes them more suitable for writing compact tests for diagnostic messages. The check_clang_tidy.py script provides an easy way to test both diag- nostic messages and fix-its. It filters out CHECK lines from the test file, runs clang-tidy and verifies messages and fixes with two separate FileCheck invocations: once with FileCheck's directive prefix set to CHECK-MESSAGES, validating the diagnostic messages, and once with the directive prefix set to CHECK-FIXES, running against the fixed code (i.e., the code after generated fix-its are applied). In particular, CHECK-FIXES: can be used to check that code was not modified by fix-its, by checking that it is present unchanged in the fixed code. The full set of FileCheck directives is available (e.g., CHECK-MES- SAGES-SAME:, CHECK-MESSAGES-NOT:), though typically the basic CHECK forms (CHECK-MESSAGES and CHECK-FIXES) are sufficient for clang-tidy tests. Note that the FileCheck documentation mostly assumes the default prefix (CHECK), and hence describes the directive as CHECK:, CHECK-SAME:, CHECK-NOT:, etc. Replace CHECK by either CHECK-FIXES or CHECK-MESSAGES for clang-tidy tests. An additional check enabled by check_clang_tidy.py ensures that if CHECK-MESSAGES: is used in a file then every warning or error must have an associated CHECK in that file. Or, you can use CHECK-NOTES: instead, if you want to also ensure that all the notes are checked. To use the check_clang_tidy.py script, put a .cpp file with the appro- priate RUN line in the test/clang-tidy directory. Use CHECK-MESSAGES: and CHECK-FIXES: lines to write checks against diagnostic messages and fixed code. It's advised to make the checks as specific as possible to avoid checks matching to incorrect parts of the input. Use [[@LINE+X]]/[[@LINE-X]] substitutions and distinct function and variable names in the test code. Here's an example of a test using the check_clang_tidy.py script (the full source code is at test/clang-tidy/checkers/google/readability-casting.cpp): // RUN: %check_clang_tidy %s google-readability-casting %t void f(int a) { int b = (int)a; // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: redundant cast to the same type [google-readability-casting] // CHECK-FIXES: int b = a; } To check more than one scenario in the same test file use -check-suf- fix=SUFFIX-NAME on check_clang_tidy.py command line or -check-suf- fixes=SUFFIX-NAME-1,SUFFIX-NAME-2,.... With -check-suffix[es]=SUF- FIX-NAME you need to replace your CHECK-* directives with CHECK-MES- SAGES-SUFFIX-NAME and CHECK-FIXES-SUFFIX-NAME. Here's an example: // RUN: %check_clang_tidy -check-suffix=USING-A %s misc-unused-using-decls %t -- -- -DUSING_A // RUN: %check_clang_tidy -check-suffix=USING-B %s misc-unused-using-decls %t -- -- -DUSING_B // RUN: %check_clang_tidy %s misc-unused-using-decls %t ... // CHECK-MESSAGES-USING-A: :[[@LINE-8]]:10: warning: using decl 'A' {{.*}} // CHECK-MESSAGES-USING-B: :[[@LINE-7]]:10: warning: using decl 'B' {{.*}} // CHECK-MESSAGES: :[[@LINE-6]]:10: warning: using decl 'C' {{.*}} // CHECK-FIXES-USING-A-NOT: using a::A;$ // CHECK-FIXES-USING-B-NOT: using a::B;$ // CHECK-FIXES-NOT: using a::C;$ There are many dark corners in the C++ language, and it may be diffi- cult to make your check work perfectly in all cases, especially if it issues fix-it hints. The most frequent pitfalls are macros and tem- plates: 1. code written in a macro body/template definition may have a differ- ent meaning depending on the macro expansion/template instantiation; 2. multiple macro expansions/template instantiations may result in the same code being inspected by the check multiple times (possibly, with different meanings, see 1), and the same warning (or a slightly different one) may be issued by the check multiple times; clang-tidy will deduplicate _identical_ warnings, but if the warnings are slightly different, all of them will be shown to the user (and used for applying fixes, if any); 3. making replacements to a macro body/template definition may be fine for some macro expansions/template instantiations, but easily break some other expansions/instantiations. If you need multiple files to exercise all the aspects of your check, it is recommended you place them in a subdirectory named for the check under the Inputs directory for the module containing your check. This keeps the test directory from getting cluttered. If you need to validate how your check interacts with system header files, a set of simulated system header files is located in the check- ers/Inputs/Headers directory. The path to this directory is available in a lit test with the variable %clang_tidy_headers. Out-of-tree check plugins Developing an out-of-tree check as a plugin largely follows the steps outlined above. The plugin is a shared library whose code lives outside the clang-tidy build system. Build and link this shared library against LLVM as done for other kinds of Clang plugins. The plugin can be loaded by passing -load to clang-tidy in addition to the names of the checks to enable. $ clang-tidy --checks=-*,my-explicit-constructor -list-checks -load myplugin.so There is no expectations regarding ABI and API stability, so the plugin must be compiled against the version of clang-tidy that will be loading the plugin. The plugins can use threads, TLS, or any other facilities available to in-tree code which is accessible from the external headers. Running clang-tidy on LLVM To test a check it's best to try it out on a larger code base. LLVM and Clang are the natural targets as you already have the source code around. The most convenient way to run clang-tidy is with a compile command database; CMake can automatically generate one, for a descrip- tion of how to enable it see How To Setup Clang Tooling For LLVM. Once compile_commands.json is in place and a working version of clang-tidy is in PATH the entire code base can be analyzed with clang-tidy/tool/run-clang-tidy.py. The script executes clang-tidy with the default set of checks on every translation unit in the compile com- mand database and displays the resulting warnings and errors. The script provides multiple configuration flags. • The default set of checks can be overridden using the -checks argu- ment, taking the identical format as clang-tidy does. For example -checks=-*,modernize-use-override will run the modernize-use-override check only. • To restrict the files examined you can provide one or more regex ar- guments that the file names are matched against. run-clang-tidy.py clang-tidy/.*Check\.cpp will only analyze clang-tidy checks. It may also be necessary to restrict the header files that warnings are dis- played from using the -header-filter flag. It has the same behavior as the corresponding clang-tidy flag. • To apply suggested fixes -fix can be passed as an argument. This gathers all changes in a temporary directory and applies them. Pass- ing -format will run clang-format over changed lines. On checks profiling clang-tidy can collect per-check profiling info, and output it for each processed source file (translation unit). To enable profiling info collection, use the -enable-check-profile ar- gument. The timings will be output to stderr as a table. Example out- put: $ clang-tidy -enable-check-profile -checks=-*,readability-function-size source.cpp ===-------------------------------------------------------------------------=== clang-tidy checks profiling ===-------------------------------------------------------------------------=== Total Execution Time: 1.0282 seconds (1.0258 wall clock) ---User Time--- --System Time-- --User+System-- ---Wall Time--- --- Name --- 0.9136 (100.0%) 0.1146 (100.0%) 1.0282 (100.0%) 1.0258 (100.0%) readability-function-size 0.9136 (100.0%) 0.1146 (100.0%) 1.0282 (100.0%) 1.0258 (100.0%) Total It can also store that data as JSON files for further processing. Exam- ple output: $ clang-tidy -enable-check-profile -store-check-profile=. -checks=-*,readability-function-size source.cpp $ # Note that there won't be timings table printed to the console. $ ls /tmp/out/ 20180516161318717446360-source.cpp.json $ cat 20180516161318717446360-source.cpp.json { "file": "/path/to/source.cpp", "timestamp": "2018-05-16 16:13:18.717446360", "profile": { "time.clang-tidy.readability-function-size.wall": 1.0421266555786133e+00, "time.clang-tidy.readability-function-size.user": 9.2088400000005421e-01, "time.clang-tidy.readability-function-size.sys": 1.2418899999999974e-01 } } There is only one argument that controls profile storage: • -store-check-profile=<prefix> By default reports are printed in tabulated format to stderr. When this option is passed, these per-TU profiles are instead stored as JSON. If the prefix is not an absolute path, it is considered to be relative to the directory from where you have run clang-tidy. All . and .. patterns in the path are collapsed, and symlinks are re- solved. Example: Let's suppose you have a source file named example.cpp, lo- cated in the /source directory. Only the input filename is used, not the full path to the source file. Additionally, it is prefixed with the current timestamp. • If you specify -store-check-profile=/tmp, then the profile will be saved to /tmp/<ISO8601-like timestamp>-example.cpp.json • If you run clang-tidy from within /foo directory, and specify -store-check-profile=., then the profile will still be saved to /foo/<ISO8601-like timestamp>-example.cpp.json clang-tidy is a clang-based C++ "linter" tool. Its purpose is to pro- vide an extensible framework for diagnosing and fixing typical program- ming errors, like style violations, interface misuse, or bugs that can be deduced via static analysis. clang-tidy is modular and provides a convenient interface for writing new checks. Using clang-tidy clang-tidy is a LibTooling-based tool, and it's easier to work with if you set up a compile command database for your project (for an example of how to do this, see How To Setup Tooling For LLVM). You can also specify compilation options on the command line after --: $ clang-tidy test.cpp -- -Imy_project/include -DMY_DEFINES ... clang-tidy has its own checks and can also run Clang Static Analyzer checks. Each check has a name and the checks to run can be chosen using the -checks= option, which specifies a comma-separated list of positive and negative (prefixed with -) globs. Positive globs add subsets of checks, and negative globs remove them. For example, $ clang-tidy test.cpp -checks=-*,clang-analyzer-*,-clang-analyzer-cplusplus* will disable all default checks (-*) and enable all clang-analyzer-* checks except for clang-analyzer-cplusplus* ones. The -list-checks option lists all the enabled checks. When used without -checks=, it shows checks enabled by default. Use -checks=* to see all available checks or with any other value of -checks= to see which checks are enabled by this value. There are currently the following groups of checks: +--------------------+----------------------------+ | Name prefix | Description | +--------------------+----------------------------+ | abseil- | Checks related to Abseil | | | library. | +--------------------+----------------------------+ | altera- | Checks related to OpenCL | | | programming for FPGAs. | +--------------------+----------------------------+ | android- | Checks related to Android. | +--------------------+----------------------------+ | boost- | Checks related to Boost | | | library. | +--------------------+----------------------------+ | bugprone- | Checks that target | | | bug-prone code constructs. | +--------------------+----------------------------+ | cert- | Checks related to CERT Se- | | | cure Coding Guidelines. | +--------------------+----------------------------+ | clang-analyzer- | Clang Static Analyzer | | | checks. | +--------------------+----------------------------+ | concurrency- | Checks related to concur- | | | rent programming (includ- | | | ing threads, fibers, | | | coroutines, etc.). | +--------------------+----------------------------+ | cppcoreguidelines- | Checks related to C++ Core | | | Guidelines. | +--------------------+----------------------------+ | darwin- | Checks related to Darwin | | | coding conventions. | +--------------------+----------------------------+ | fuchsia- | Checks related to Fuchsia | | | coding conventions. | +--------------------+----------------------------+ | google- | Checks related to Google | | | coding conventions. | +--------------------+----------------------------+ | hicpp- | Checks related to High In- | | | tegrity C++ Coding Stan- | | | dard. | +--------------------+----------------------------+ | linuxkernel- | Checks related to the | | | Linux Kernel coding con- | | | ventions. | +--------------------+----------------------------+ | llvm- | Checks related to the LLVM | | | coding conventions. | +--------------------+----------------------------+ | llvmlibc- | Checks related to the | | | LLVM-libc coding stan- | | | dards. | +--------------------+----------------------------+ | misc- | Checks that we didn't have | | | a better category for. | +--------------------+----------------------------+ | modernize- | Checks that advocate usage | | | of modern (currently "mod- | | | ern" means "C++11") lan- | | | guage constructs. | +--------------------+----------------------------+ | mpi- | Checks related to MPI | | | (Message Passing Inter- | | | face). | +--------------------+----------------------------+ | objc- | Checks related to Objec- | | | tive-C coding conventions. | +--------------------+----------------------------+ | openmp- | Checks related to OpenMP | | | API. | +--------------------+----------------------------+ | performance- | Checks that target perfor- | | | mance-related issues. | +--------------------+----------------------------+ | portability- | Checks that target porta- | | | bility-related issues that | | | don't relate to any par- | | | ticular coding style. | +--------------------+----------------------------+ | readability- | Checks that target read- | | | ability-related issues | | | that don't relate to any | | | particular coding style. | +--------------------+----------------------------+ | zircon- | Checks related to Zircon | | | kernel coding conventions. | +--------------------+----------------------------+ Clang diagnostics are treated in a similar way as check diagnostics. Clang diagnostics are displayed by clang-tidy and can be filtered out using the -checks= option. However, the -checks= option does not affect compilation arguments, so it cannot turn on Clang warnings which are not already turned on in the build configuration. The -warnings-as-er- rors= option upgrades any warnings emitted under the -checks= flag to errors (but it does not enable any checks itself). Clang diagnostics have check names starting with clang-diagnostic-. Diagnostics which have a corresponding warning option, are named clang-diagnostic-<warning-option>, e.g. Clang warning controlled by -Wliteral-conversion will be reported with check name clang-diagnos- tic-literal-conversion. The -fix flag instructs clang-tidy to fix found errors if supported by corresponding checks. An overview of all the command-line options: $ clang-tidy --help USAGE: clang-tidy [options] <source0> [... <sourceN>] OPTIONS: Generic Options: --help - Display available options (--help-hidden for more) --help-list - Display list of available options (--help-list-hidden for more) --version - Display the version of this program clang-tidy options: --checks=<string> - Comma-separated list of globs with optional '-' prefix. Globs are processed in order of appearance in the list. Globs without '-' prefix add checks with matching names to the set, globs with the '-' prefix remove checks with matching names from the set of enabled checks. This option's value is appended to the value of the 'Checks' option in .clang-tidy file, if any. --config=<string> - Specifies a configuration in YAML/JSON format: -config="{Checks: '*', CheckOptions: {x: y}}" When the value is empty, clang-tidy will attempt to find a file named .clang-tidy for each source file in its parent directories. --config-file=<string> - Specify the path of .clang-tidy or custom config file: e.g. --config-file=/some/path/myTidyConfigFile This option internally works exactly the same way as --config option after reading specified config file. Use either --config-file or --config, not both. --dump-config - Dumps configuration in the YAML format to stdout. This option can be used along with a file name (and '--' if the file is outside of a project with configured compilation database). The configuration used for this file will be printed. Use along with -checks=* to include configuration of all checks. --enable-check-profile - Enable per-check timing profiles, and print a report to stderr. --enable-module-headers-parsing - Enables preprocessor-level module header parsing for C++20 and above, empowering specific checks to detect macro definitions within modules. This feature may cause performance and parsing issues and is therefore considered experimental. --explain-config - For each enabled check explains, where it is enabled, i.e. in clang-tidy binary, command line or a specific configuration file. --export-fixes=<filename> - YAML file to store suggested fixes in. The stored fixes can be applied to the input source code with clang-apply-replacements. --extra-arg=<string> - Additional argument to append to the compiler command line --extra-arg-before=<string> - Additional argument to prepend to the compiler command line --fix - Apply suggested fixes. Without -fix-errors clang-tidy will bail out if any compilation errors were found. --fix-errors - Apply suggested fixes even if compilation errors were found. If compiler errors have attached fix-its, clang-tidy will apply them as well. --fix-notes - If a warning has no fix, but a single fix can be found through an associated diagnostic note, apply the fix. Specifying this flag will implicitly enable the '--fix' flag. --format-style=<string> - Style for formatting code around applied fixes: - 'none' (default) turns off formatting - 'file' (literally 'file', not a placeholder) uses .clang-format file in the closest parent directory - '{ <json> }' specifies options inline, e.g. -format-style='{BasedOnStyle: llvm, IndentWidth: 8}' - 'llvm', 'google', 'webkit', 'mozilla' See clang-format documentation for the up-to-date information about formatting styles and options. This option overrides the 'FormatStyle` option in .clang-tidy file, if any. --header-filter=<string> - Regular expression matching the names of the headers to output diagnostics from. Diagnostics from the main file of each translation unit are always displayed. Can be used together with -line-filter. This option overrides the 'HeaderFilterRegex' option in .clang-tidy file, if any. --line-filter=<string> - List of files with line ranges to filter the warnings. Can be used together with -header-filter. The format of the list is a JSON array of objects: [ {"name":"file1.cpp","lines":[[1,3],[5,7]]}, {"name":"file2.h"} ] --list-checks - List all enabled checks and exit. Use with -checks=* to list all available checks. --load=<pluginfilename> - Load the specified plugin -p <string> - Build path --quiet - Run clang-tidy in quiet mode. This suppresses printing statistics about ignored warnings and warnings treated as errors if the respective options are specified. --store-check-profile=<prefix> - By default reports are printed in tabulated format to stderr. When this option is passed, these per-TU profiles are instead stored as JSON. --system-headers - Display the errors from system headers. This option overrides the 'SystemHeaders' option in .clang-tidy file, if any. --use-color - Use colors in diagnostics. If not set, colors will be used if the terminal connected to standard output supports colors. This option overrides the 'UseColor' option in .clang-tidy file, if any. --verify-config - Check the config files to ensure each check and option is recognized. --vfsoverlay=<filename> - Overlay the virtual filesystem described by file over the real file system. --warnings-as-errors=<string> - Upgrades warnings to errors. Same format as '-checks'. This option's value is appended to the value of the 'WarningsAsErrors' option in .clang-tidy file, if any. -p <build-path> is used to read a compile command database. For example, it can be a CMake build directory in which a file named compile_commands.json exists (use -DCMAKE_EXPORT_COMPILE_COMMANDS=ON CMake option to get this output). When no build path is specified, a search for compile_commands.json will be attempted through all parent paths of the first input file . See: https://clang.llvm.org/docs/HowToSetupToolingForLLVM.html for an example of setting up Clang Tooling on a source tree. <source0> ... specify the paths of source files. These paths are looked up in the compile command database. If the path of a file is absolute, it needs to point into CMake's source tree. If the path is relative, the current working directory needs to be in the CMake source tree and the file must be in a subdirectory of the current working directory. "./" prefixes in the relative files will be automatically removed, but the rest of a relative path must be a suffix of a path in the compile command database. Configuration files: clang-tidy attempts to read configuration for each source file from a .clang-tidy file located in the closest parent directory of the source file. The .clang-tidy file is specified in YAML format. If any configuration options have a corresponding command-line option, command-line option takes precedence. The following configuration options may be used in a .clang-tidy file: CheckOptions - List of key-value pairs defining check-specific options. Example: CheckOptions: some-check.SomeOption: 'some value' Checks - Same as '--checks'. Additionally, the list of globs can be specified as a list instead of a string. ExtraArgs - Same as '--extra-args'. ExtraArgsBefore - Same as '--extra-args-before'. FormatStyle - Same as '--format-style'. HeaderFileExtensions - File extensions to consider to determine if a given diagnostic is located in a header file. HeaderFilterRegex - Same as '--header-filter-regex'. ImplementationFileExtensions - File extensions to consider to determine if a given diagnostic is located in an implementation file. InheritParentConfig - If this option is true in a config file, the configuration file in the parent directory (if any exists) will be taken and the current config file will be applied on top of the parent one. SystemHeaders - Same as '--system-headers'. UseColor - Same as '--use-color'. User - Specifies the name or e-mail of the user running clang-tidy. This option is used, for example, to place the correct user name in TODO() comments in the relevant check. WarningsAsErrors - Same as '--warnings-as-errors'. The effective configuration can be inspected using --dump-config: $ clang-tidy --dump-config --- Checks: '-*,some-check' WarningsAsErrors: '' HeaderFileExtensions: ['', 'h','hh','hpp','hxx'] ImplementationFileExtensions: ['c','cc','cpp','cxx'] HeaderFilterRegex: '' FormatStyle: none InheritParentConfig: true User: user CheckOptions: some-check.SomeOption: 'some value' ... Suppressing Undesired Diagnostics clang-tidy diagnostics are intended to call out code that does not ad- here to a coding standard, or is otherwise problematic in some way. However, if the code is known to be correct, it may be useful to si- lence the warning. Some clang-tidy checks provide a check-specific way to silence the diagnostics, e.g. bugprone-use-after-move can be si- lenced by re-initializing the variable after it has been moved out, bugprone-string-integer-assignment can be suppressed by explicitly casting the integer to char, readability-implicit-bool-conversion can also be suppressed by using explicit casts, etc. If a specific suppression mechanism is not available for a certain warning, or its use is not desired for some reason, clang-tidy has a generic mechanism to suppress diagnostics using NOLINT, NOLINTNEXTLINE, and NOLINTBEGIN ... NOLINTEND comments. The NOLINT comment instructs clang-tidy to ignore warnings on the same line (it doesn't apply to a function, a block of code or any other lan- guage construct; it applies to the line of code it is on). If introduc- ing the comment on the same line would change the formatting in an un- desired way, the NOLINTNEXTLINE comment allows suppressing clang-tidy warnings on the next line. The NOLINTBEGIN and NOLINTEND comments allow suppressing clang-tidy warnings on multiple lines (affecting all lines between the two comments). All comments can be followed by an optional list of check names in parentheses (see below for the formal syntax). The list of check names supports globbing, with the same format and semantics as for enabling checks. Note: negative globs are ignored here, as they would effec- tively re-activate the warning. For example: class Foo { // Suppress all the diagnostics for the line Foo(int param); // NOLINT // Consider explaining the motivation to suppress the warning Foo(char param); // NOLINT: Allow implicit conversion from `char`, because <some valid reason> // Silence only the specified checks for the line Foo(double param); // NOLINT(google-explicit-constructor, google-runtime-int) // Silence all checks from the `google` module Foo(bool param); // NOLINT(google*) // Silence all checks ending with `-avoid-c-arrays` int array[10]; // NOLINT(*-avoid-c-arrays) // Silence only the specified diagnostics for the next line // NOLINTNEXTLINE(google-explicit-constructor, google-runtime-int) Foo(bool param); // Silence all checks from the `google` module for the next line // NOLINTNEXTLINE(google*) Foo(bool param); // Silence all checks ending with `-avoid-c-arrays` for the next line // NOLINTNEXTLINE(*-avoid-c-arrays) int array[10]; // Silence only the specified checks for all lines between the BEGIN and END // NOLINTBEGIN(google-explicit-constructor, google-runtime-int) Foo(short param); Foo(long param); // NOLINTEND(google-explicit-constructor, google-runtime-int) // Silence all checks from the `google` module for all lines between the BEGIN and END // NOLINTBEGIN(google*) Foo(bool param); // NOLINTEND(google*) // Silence all checks ending with `-avoid-c-arrays` for all lines between the BEGIN and END // NOLINTBEGIN(*-avoid-c-arrays) int array[10]; // NOLINTEND(*-avoid-c-arrays) }; The formal syntax of NOLINT, NOLINTNEXTLINE, and NOLINTBEGIN ... NO- LINTEND is the following: lint-comment: lint-command lint-command lint-args lint-args: ( check-name-list ) check-name-list: check-name check-name-list , check-name lint-command: NOLINT NOLINTNEXTLINE NOLINTBEGIN NOLINTEND Note that whitespaces between NOLINT/NOLINTNEXTLINE/NOLINTBEGIN/NOLIN- TEND and the opening parenthesis are not allowed (in this case the com- ment will be treated just as NOLINT/NOLINTNEXTLINE/NOLINTBEGIN/NOLIN- TEND), whereas in the check names list (inside the parentheses), white- spaces can be used and will be ignored. All NOLINTBEGIN comments must be paired by an equal number of NOLINTEND comments. Moreover, a pair of comments must have matching arguments -- for example, NOLINTBEGIN(check-name) can be paired with NOLIN- TEND(check-name) but not with NOLINTEND (zero arguments). clang-tidy will generate a clang-tidy-nolint error diagnostic if any NOLINTBE- GIN/NOLINTEND comment violates these requirements. CLANG-INCLUDE-FIXER Contents • Clang-Include-Fixer • Setup • Creating a Symbol Index From a Compilation Database • Integrate with Vim • Integrate with Emacs • How it Works One of the major nuisances of C++ compared to other languages is the manual management of #include directives in any file. clang-in- clude-fixer addresses one aspect of this problem by providing an auto- mated way of adding #include directives for missing symbols in one translation unit. While inserting missing #include, clang-include-fixer adds missing namespace qualifiers to all instances of an unidentified symbol if the symbol is missing some prefix namespace qualifiers. Setup To use clang-include-fixer two databases are required. Both can be gen- erated with existing tools. • Compilation database. Contains the compiler commands for any given file in a project and can be generated by CMake, see How To Setup Tooling For LLVM. • Symbol index. Contains all symbol information in a project to match a given identifier to a header file. Ideally both databases (compile_commands.json and find_all_sym- bols_db.yaml) are linked into the root of the source tree they corre- spond to. Then the clang-include-fixer can automatically pick them up if called with a source file from that tree. Note that by default com- pile_commands.json as generated by CMake does not include header files, so only implementation files can be handled by tools. Creating a Symbol Index From a Compilation Database The include fixer contains find-all-symbols, a tool to create a symbol database in YAML format from a compilation database by parsing all source files listed in it. The following list of commands shows how to set up a database for LLVM, any project built by CMake should follow similar steps. $ cd path/to/llvm-build $ ninja find-all-symbols // build find-all-symbols tool. $ ninja clang-include-fixer // build clang-include-fixer tool. $ ls compile_commands.json # Make sure compile_commands.json exists. compile_commands.json $ path/to/llvm/source/clang-tools-extra/clang-include-fixer/find-all-symbols/tool/run-find-all-symbols.py ... wait as clang indexes the code base ... $ ln -s $PWD/find_all_symbols_db.yaml path/to/llvm/source/ # Link database into the source tree. $ ln -s $PWD/compile_commands.json path/to/llvm/source/ # Also link compilation database if it's not there already. $ cd path/to/llvm/source $ /path/to/clang-include-fixer -db=yaml path/to/file/with/missing/include.cpp Added #include "foo.h" Integrate with Vim To run clang-include-fixer on a potentially unsaved buffer in Vim. Add the following key binding to your .vimrc: noremap <leader>cf :pyf path/to/llvm/source/clang-tools-extra/clang-include-fixer/tool/clang-include-fixer.py<cr> This enables clang-include-fixer for NORMAL and VISUAL mode. Change <leader>cf to another binding if you need clang-include-fixer on a dif- ferent key. The <leader> key is a reference to a specific key defined by the mapleader variable and is bound to backslash by default. Make sure vim can find clang-include-fixer: • Add the path to clang-include-fixer to the PATH environment variable. • Or set g:clang_include_fixer_path in vimrc: let g:clang_in- clude_fixer_path=path/to/clang-include-fixer You can customize the number of headers being shown by setting let g:clang_include_fixer_maximum_suggested_headers=5 Customized settings in .vimrc: • let g:clang_include_fixer_path = "clang-include-fixer" Set clang-include-fixer binary file path. • let g:clang_include_fixer_maximum_suggested_headers = 3 Set the maximum number of #includes to show. Default is 3. • let g:clang_include_fixer_increment_num = 5 Set the increment number of #includes to show every time when press- ing m. Default is 5. • let g:clang_include_fixer_jump_to_include = 0 Set to 1 if you want to jump to the new inserted #include line. De- fault is 0. • let g:clang_include_fixer_query_mode = 0 Set to 1 if you want to insert #include for the symbol under the cur- sor. Default is 0. Compared to normal mode, this mode won't parse the source file and only search the symbol from database, which is faster than normal mode. See clang-include-fixer.py for more details. Integrate with Emacs To run clang-include-fixer on a potentially unsaved buffer in Emacs. Ensure that Emacs finds clang-include-fixer.el by adding the directory containing the file to the load-path and requiring the clang-in- clude-fixer in your .emacs: (add-to-list 'load-path "path/to/llvm/source/clang-tools-extra/clang-include-fixer/tool/" (require 'clang-include-fixer) Within Emacs the tool can be invoked with the command M-x clang-in- clude-fixer. This will insert the header that defines the first unde- fined symbol; if there is more than one header that would define the symbol, the user is prompted to select one. To include the header that defines the symbol at point, run M-x clang-include-fixer-at-point. Make sure Emacs can find clang-include-fixer: • Either add the parent directory of clang-include-fixer to the PATH environment variable, or customize the Emacs user option clang-in- clude-fixer-executable to point to the file name of the program. How it Works To get the most information out of Clang at parse time, clang-in- clude-fixer runs in tandem with the parse and receives callbacks from Clang's semantic analysis. In particular it reuses the existing support for typo corrections. Whenever Clang tries to correct a potential typo it emits a callback to the include fixer which then looks for a corre- sponding file. At this point rich lookup information is still avail- able, which is not available in the AST at a later stage. The identifier that should be typo corrected is then sent to the data- base, if a header file is returned it is added as an include directive at the top of the file. Currently clang-include-fixer only inserts a single include at a time to avoid getting caught in follow-up errors. If multiple #include addi- tions are desired the program can be rerun until a fix-point is reached. MODULARIZE USER'S MANUAL Modularize Usage modularize [<modularize-options>] [<module-map>|<include-files-list>]* [<front-end-options>...] <modularize-options> is a place-holder for options specific to modular- ize, which are described below in Modularize Command Line Options. <module-map> specifies the path of a file name for an existing module map. The module map must be well-formed in terms of syntax. Modularize will extract the header file names from the map. Only normal headers are checked, assuming headers marked "private", "textual", or "exclude" are not to be checked as a top-level include, assuming they either are included by other headers which are checked, or they are not suitable for modules. <include-files-list> specifies the path of a file name for a file con- taining the newline-separated list of headers to check with respect to each other. Lines beginning with '#' and empty lines are ignored. Header file names followed by a colon and other space-separated file names will include those extra files as dependencies. The file names can be relative or full paths, but must be on the same line. For exam- ple: header1.h header2.h header3.h: header1.h header2.h Note that unless a -prefix (header path) option is specified, non-ab- solute file paths in the header list file will be relative to the header list file directory. Use -prefix to specify a different direc- tory. <front-end-options> is a place-holder for regular Clang front-end argu- ments, which must follow the <include-files-list>. Note that by de- fault, modularize assumes .h files contain C++ source, so if you are using a different language, you might need to use a -x option to tell Clang that the header contains another language, i.e.: -x c Note also that because modularize does not use the clang driver, you will likely need to pass in additional compiler front-end arguments to match those passed in by default by the driver. Modularize Command Line Options -prefix=<header-path> Prepend the given path to non-absolute file paths in the header list file. By default, headers are assumed to be relative to the header list file directory. Use -prefix to specify a differ- ent directory. -module-map-path=<module-map-path> Generate a module map and output it to the given file. See the description in Module Map Generation. -problem-files-list=<problem-files-list-file-name> For use only with module map assistant. Input list of files that have problems with respect to modules. These will still be in- cluded in the generated module map, but will be marked as "ex- cluded" headers. -root-module=<root-name> Put modules generated by the -module-map-path option in an en- closing module with the given name. See the description in Module Map Generation. -block-check-header-list-only Limit the #include-inside-extern-or-namespace-block check to only those headers explicitly listed in the header list. This is a work-around for avoiding error messages for private in- cludes that purposefully get included inside blocks. -no-coverage-check Don't do the coverage check for a module map. -coverage-check-only Only do the coverage check for a module map. -display-file-lists Display lists of good files (no compile errors), problem files, and a combined list with problem files preceded by a '#'. This can be used to quickly determine which files have problems. The latter combined list might be useful in starting to modularize a set of headers. You can start with a full list of headers, use -display-file-lists option, and then use the combined list as your intermediate list, uncommenting-out headers as you fix them. modularize is a standalone tool that checks whether a set of headers provides the consistent definitions required to use modules. For exam- ple, it detects whether the same entity (say, a NULL macro or size_t typedef) is defined in multiple headers or whether a header produces different definitions under different circumstances. These conditions cause modules built from the headers to behave poorly, and should be fixed before introducing a module map. modularize also has an assistant mode option for generating a module map file based on the provided header list. The generated file is a functional module map that can be used as a starting point for a mod- ule.modulemap file. Getting Started To build from source: 1. Read Getting Started with the LLVM System and Clang Tools Documenta- tion for information on getting sources for LLVM, Clang, and Clang Extra Tools. 2. Getting Started with the LLVM System and Building LLVM with CMake give directions for how to build. With sources all checked out into the right place the LLVM build will build Clang Extra Tools and their dependencies automatically. • If using CMake, you can also use the modularize target to build just the modularize tool and its dependencies. Before continuing, take a look at Modularize Usage to see how to invoke modularize. What Modularize Checks Modularize will check for the following: • Duplicate global type and variable definitions • Duplicate macro definitions • Macro instances, 'defined(macro)', or #if, #elif, #ifdef, #ifndef conditions that evaluate differently in a header • #include directives inside 'extern "C/C++" {}' or 'namespace (name) {}' blocks • Module map header coverage completeness (in the case of a module map input only) Modularize will do normal C/C++ parsing, reporting normal errors and warnings, but will also report special error messages like the follow- ing: error: '(symbol)' defined at multiple locations: (file):(row):(column) (file):(row):(column) error: header '(file)' has different contents depending on how it was included The latter might be followed by messages like the following: note: '(symbol)' in (file) at (row):(column) not always provided Checks will also be performed for macro expansions, defined(macro) ex- pressions, and preprocessor conditional directives that evaluate incon- sistently, and can produce error messages like the following: (...)/SubHeader.h:11:5: #if SYMBOL == 1 ^ error: Macro instance 'SYMBOL' has different values in this header, depending on how it was included. 'SYMBOL' expanded to: '1' with respect to these inclusion paths: (...)/Header1.h (...)/SubHeader.h (...)/SubHeader.h:3:9: #define SYMBOL 1 ^ Macro defined here. 'SYMBOL' expanded to: '2' with respect to these inclusion paths: (...)/Header2.h (...)/SubHeader.h (...)/SubHeader.h:7:9: #define SYMBOL 2 ^ Macro defined here. Checks will also be performed for '#include' directives that are nested inside 'extern "C/C++" {}' or 'namespace (name) {}' blocks, and can produce error message like the following: IncludeInExtern.h:2:3: #include "Empty.h" ^ error: Include directive within extern "C" {}. IncludeInExtern.h:1:1: extern "C" { ^ The "extern "C" {}" block is here. Module Map Coverage Check The coverage check uses the Clang library to read and parse the module map file. Starting at the module map file directory, or just the in- clude paths, if specified, it will collect the names of all the files it considers headers (no extension, .h, or .inc--if you need more, mod- ify the isHeader function). It then compares the headers against those referenced in the module map, either explicitly named, or implicitly named via an umbrella directory or umbrella file, as parsed by the Mod- uleMap object. If headers are found which are not referenced or cov- ered by an umbrella directory or file, warning messages will be pro- duced, and this program will return an error code of 1. If no problems are found, an error code of 0 is returned. Note that in the case of umbrella headers, this tool invokes the com- piler to preprocess the file, and uses a callback to collect the header files included by the umbrella header or any of its nested includes. If any front end options are needed for these compiler invocations, these can be included on the command line after the module map file argument. Warning message have the form: warning: module.modulemap does not account for file: Level3A.h Note that for the case of the module map referencing a file that does not exist, the module map parser in Clang will (at the time of this writing) display an error message. To limit the checks modularize does to just the module map coverage check, use the -coverage-check-only option. For example: modularize -coverage-check-only module.modulemap Module Map Generation If you specify the -module-map-path=<module map file>, modularize will output a module map based on the input header list. A module will be created for each header. Also, if the header in the header list is a partial path, a nested module hierarchy will be created in which a mod- ule will be created for each subdirectory component in the header path, with the header itself represented by the innermost module. If other headers use the same subdirectories, they will be enclosed in these same modules also. For example, for the header list: SomeTypes.h SomeDecls.h SubModule1/Header1.h SubModule1/Header2.h SubModule2/Header3.h SubModule2/Header4.h SubModule2.h The following module map will be generated: // Output/NoProblemsAssistant.txt // Generated by: modularize -module-map-path=Output/NoProblemsAssistant.txt \ -root-module=Root NoProblemsAssistant.modularize module SomeTypes { header "SomeTypes.h" export * } module SomeDecls { header "SomeDecls.h" export * } module SubModule1 { module Header1 { header "SubModule1/Header1.h" export * } module Header2 { header "SubModule1/Header2.h" export * } } module SubModule2 { module Header3 { header "SubModule2/Header3.h" export * } module Header4 { header "SubModule2/Header4.h" export * } header "SubModule2.h" export * } An optional -root-module=<root-name> option can be used to cause a root module to be created which encloses all the modules. An optional -problem-files-list=<problem-file-name> can be used to in- put a list of files to be excluded, perhaps as a temporary stop-gap measure until problem headers can be fixed. For example, with the same header list from above: // Output/NoProblemsAssistant.txt // Generated by: modularize -module-map-path=Output/NoProblemsAssistant.txt \ -root-module=Root NoProblemsAssistant.modularize module Root { module SomeTypes { header "SomeTypes.h" export * } module SomeDecls { header "SomeDecls.h" export * } module SubModule1 { module Header1 { header "SubModule1/Header1.h" export * } module Header2 { header "SubModule1/Header2.h" export * } } module SubModule2 { module Header3 { header "SubModule2/Header3.h" export * } module Header4 { header "SubModule2/Header4.h" export * } header "SubModule2.h" export * } } Note that headers with dependents will be ignored with a warning, as the Clang module mechanism doesn't support headers the rely on other headers to be included first. The module map format defines some keywords which can't be used in mod- ule names. If a header has one of these names, an underscore ('_') will be prepended to the name. For example, if the header name is header.h, because header is a keyword, the module name will be _header. For a list of the module map keywords, please see: Lexical structure PP-TRACE USER'S MANUAL pp-trace is a standalone tool that traces preprocessor activity. It's also used as a test of Clang's PPCallbacks interface. It runs a given source file through the Clang preprocessor, displaying selected infor- mation from callback functions overridden in a PPCallbacks derivation. The output is in a high-level YAML format, described in pp-trace Output Format. pp-trace Usage Command Line Format pp-trace [<pp-trace-options>] <source-file> [-- <front-end-options>] <pp-trace-options> is a place-holder for options specific to pp-trace, which are described below in Command Line Options. <source-file> specifies the source file to run through the preproces- sor. <front-end-options> is a place-holder for regular Clang Compiler Op- tions, which must follow the <source-file>. Command Line Options -callbacks <comma-separated-globs> This option specifies a comma-separated list of globs describing the list of callbacks that should be traced. Globs are processed in order of appearance. Positive globs add matched callbacks to the set, negative globs (those with the '-' prefix) remove callacks from the set. • FileChanged • FileSkipped • InclusionDirective • moduleImport • EndOfMainFile • Ident • PragmaDirective • PragmaComment • PragmaDetectMismatch • PragmaDebug • PragmaMessage • PragmaDiagnosticPush • PragmaDiagnosticPop • PragmaDiagnostic • PragmaOpenCLExtension • PragmaWarning • PragmaWarningPush • PragmaWarningPop • MacroExpands • MacroDefined • MacroUndefined • Defined • SourceRangeSkipped • If • Elif • Ifdef • Ifndef • Else • Endif -output <output-file> By default, pp-trace outputs the trace information to stdout. Use this option to output the trace information to a file. pp-trace Output Format The pp-trace output is formatted as YAML. See https://yaml.org/ for general YAML information. It's arranged as a sequence of information about the callback call, including the callback name and argument in- formation, for example:: --- - Callback: Name Argument1: Value1 Argument2: Value2 (etc.) ... With real data:: --- - Callback: FileChanged Loc: "c:/Clang/llvm/clang-tools-extra/test/pp-trace/pp-trace-include.cpp:1:1" Reason: EnterFile FileType: C_User PrevFID: (invalid) (etc.) - Callback: FileChanged Loc: "D:/Clang/llvm/clang-tools-extra/test/pp-trace/pp-trace-include.cpp:5:1" Reason: ExitFile FileType: C_User PrevFID: "D:/Clang/llvm/clang-tools-extra/test/pp-trace/Input/Level1B.h" - Callback: EndOfMainFile ... In all but one case (MacroDirective) the "Argument" scalars have the same name as the argument in the corresponding PPCallbacks callback function. Callback Details The following sections describe the purpose and output format for each callback. Click on the callback name in the section heading to see the Doxygen documentation for the callback. The argument descriptions table describes the callback argument infor- mation displayed. The Argument Name field in most (but not all) cases is the same name as the callback function parameter. The Argument Value Syntax field describes the values that will be dis- played for the argument value. It uses an ad hoc representation that mixes literal and symbolic representations. Enumeration member symbols are shown as the actual enum member in a (member1|member2|...) form. A name in parentheses can either represent a place holder for the de- scribed value, or confusingly, it might be a literal, such as (null), for a null pointer. Locations are shown as quoted only to avoid con- fusing the documentation generator. The Clang C++ Type field is the type from the callback function decla- ration. The description describes the argument or what is displayed for it. Note that in some cases, such as when a structure pointer is an argu- ment value, only some key member or members are shown to represent the value, instead of trying to display all members of the structure. FileChanged Callback FileChanged is called when the preprocessor enters or exits a file, both the top level file being compiled, as well as any #include direc- tives. It will also be called as a result of a system header pragma or in internal renaming of a file. Argument descriptions: +---------------+-----------------------+------------------+------------------+ | Argument Name | Argument Value | Clang C++ Type | Description | | | Syntax | | | +---------------+-----------------------+------------------+------------------+ | Loc | "(file):(line):(col)" | SourceLocation | The location of | | | | | the directive. | +---------------+-----------------------+------------------+------------------+ | Reason | (EnterFile|Exit- | PPCall- | Reason for | | | File|SystemHeader- | backs::FileChan- | change. | | | Pragma|RenameFile) | geReason | | +---------------+-----------------------+------------------+------------------+ | FileType | (C_User|C_Sys- | SrcMgr::Charac- | Include type. | | | tem|C_ExternCSystem) | teristicKind | | +---------------+-----------------------+------------------+------------------+ | PrevFID | ((file)|(invalid)) | FileID | Previous file, | | | | | if any. | +---------------+-----------------------+------------------+------------------+ Example:: - Callback: FileChanged Loc: "D:/Clang/llvm/clang-tools-extra/test/pp-trace/pp-trace-include.cpp:1:1" Reason: EnterFile FileType: C_User PrevFID: (invalid) FileSkipped Callback FileSkipped is called when a source file is skipped as the result of header guard optimization. Argument descriptions: +---------------+------------------+-----------------+------------------+ | Argument Name | Argument Value | Clang C++ Type | Description | | | Syntax | | | +---------------+------------------+-----------------+------------------+ | ParentFile | ("(file)" or | const FileEntry | The file that | | | (null)) | | #included the | | | | | skipped file. | +---------------+------------------+-----------------+------------------+ | FilenameTok | (token) | const Token | The token in | | | | | ParentFile that | | | | | indicates the | | | | | skipped file. | +---------------+------------------+-----------------+------------------+ | FileType | (C_User|C_Sys- | SrcMgr::Charac- | The file type. | | | tem|C_ExternC- | teristicKind | | | | System) | | | +---------------+------------------+-----------------+------------------+ Example:: - Callback: FileSkipped ParentFile: "/path/filename.h" FilenameTok: "filename.h" FileType: C_User InclusionDirective Callback InclusionDirective is called when an inclusion directive of any kind (#include</code>, #import</code>, etc.) has been processed, regardless of whether the inclusion will actually result in an inclusion. Argument descriptions: +---------------+-----------------------+-----------------+------------------+ | Argument Name | Argument Value | Clang C++ Type | Description | | | Syntax | | | +---------------+-----------------------+-----------------+------------------+ | HashLoc | "(file):(line):(col)" | SourceLocation | The location of | | | | | the '#' that | | | | | starts the in- | | | | | clusion direc- | | | | | tive. | +---------------+-----------------------+-----------------+------------------+ | IncludeTok | (token) | const Token | The token that | | | | | indicates the | | | | | kind of inclu- | | | | | sion directive, | | | | | e.g., 'include' | | | | | or 'import'. | +---------------+-----------------------+-----------------+------------------+ | FileName | "(file)" | StringRef | The name of the | | | | | file being in- | | | | | cluded, as writ- | | | | | ten in the | | | | | source code. | +---------------+-----------------------+-----------------+------------------+ | IsAngled | (true|false) | bool | Whether the file | | | | | name was en- | | | | | closed in angle | | | | | brackets; other- | | | | | wise, it was en- | | | | | closed in | | | | | quotes. | +---------------+-----------------------+-----------------+------------------+ | FilenameRange | "(file)" | CharSourceRange | The character | | | | | range of the | | | | | quotes or angle | | | | | brackets for the | | | | | written file | | | | | name. | +---------------+-----------------------+-----------------+------------------+ | File | "(file)" | const FileEntry | The actual file | | | | | that may be in- | | | | | cluded by this | | | | | inclusion direc- | | | | | tive. | +---------------+-----------------------+-----------------+------------------+ | SearchPath | "(path)" | StringRef | Contains the | | | | | search path | | | | | which was used | | | | | to find the file | | | | | in the file sys- | | | | | tem. | +---------------+-----------------------+-----------------+------------------+ | RelativePath | "(path)" | StringRef | The path rela- | | | | | tive to Search- | | | | | Path, at which | | | | | the include file | | | | | was found. | +---------------+-----------------------+-----------------+------------------+ | Imported | ((module | const Module | The module, | | | name)|(null)) | | whenever an in- | | | | | clusion direc- | | | | | tive was auto- | | | | | matically turned | | | | | into a module | | | | | import or null | | | | | otherwise. | +---------------+-----------------------+-----------------+------------------+ Example:: - Callback: InclusionDirective HashLoc: "D:/Clang/llvmnewmod/clang-tools-extra/test/pp-trace/pp-trace-include.cpp:4:1" IncludeTok: include FileName: "Input/Level1B.h" IsAngled: false FilenameRange: "Input/Level1B.h" File: "D:/Clang/llvmnewmod/clang-tools-extra/test/pp-trace/Input/Level1B.h" SearchPath: "D:/Clang/llvmnewmod/clang-tools-extra/test/pp-trace" RelativePath: "Input/Level1B.h" Imported: (null) moduleImport Callback moduleImport is called when there was an explicit module-import syntax. Argument descriptions: +---------------+-----------------------+----------------+------------------+ | Argument Name | Argument Value | Clang C++ Type | Description | | | Syntax | | | +---------------+-----------------------+----------------+------------------+ | ImportLoc | "(file):(line):(col)" | SourceLocation | The location of | | | | | import directive | | | | | token. | +---------------+-----------------------+----------------+------------------+ | Path | "(path)" | ModuleIdPath | The identifiers | | | | | (and their loca- | | | | | tions) of the | | | | | module "path". | +---------------+-----------------------+----------------+------------------+ | Imported | ((module | const Module | The imported | | | name)|(null)) | | module; can be | | | | | null if import- | | | | | ing failed. | +---------------+-----------------------+----------------+------------------+ Example:: - Callback: moduleImport ImportLoc: "d:/Clang/llvm/clang-tools-extra/test/pp-trace/pp-trace-modules.cpp:4:2" Path: [{Name: Level1B, Loc: "d:/Clang/llvmnewmod/clang-tools-extra/test/pp-trace/pp-trace-modules.cpp:4:9"}, {Name: Level2B, Loc: "d:/Clang/llvmnewmod/clang-tools-extra/test/pp-trace/pp-trace-modules.cpp:4:17"}] Imported: Level2B EndOfMainFile Callback EndOfMainFile is called when the end of the main file is reached. Argument descriptions: +----------------+------------------+----------------+-------------+ | Argument Name | Argument Value | Clang C++ Type | Description | | | Syntax | | | +----------------+------------------+----------------+-------------+ | (no arguments) | | | | +----------------+------------------+----------------+-------------+ Example:: - Callback: EndOfMainFile Ident Callback Ident is called when a #ident or #sccs directive is read. Argument descriptions: +---------------+-----------------------+----------------+------------------+ | Argument Name | Argument Value | Clang C++ Type | Description | | | Syntax | | | +---------------+-----------------------+----------------+------------------+ | Loc | "(file):(line):(col)" | SourceLocation | The location of | | | | | the directive. | +---------------+-----------------------+----------------+------------------+ | str | (name) | const | The text of the | | | | std::string | directive. | +---------------+-----------------------+----------------+------------------+ Example:: - Callback: Ident Loc: "D:/Clang/llvm/clang-tools-extra/test/pp-trace/pp-trace-ident.cpp:3:1" str: "$Id$" PragmaDirective Callback PragmaDirective is called when start reading any pragma directive. Argument descriptions: +---------------+----------------------------------+-----------------+------------------+ | Argument Name | Argument Value | Clang C++ Type | Description | | | Syntax | | | +---------------+----------------------------------+-----------------+------------------+ | Loc | "(file):(line):(col)" | SourceLocation | The location of | | | | | the directive. | +---------------+----------------------------------+-----------------+------------------+ | Introducer | (PIK_Hash- | PragmaIntroduc- | The type of the | | | Pragma|PIK__Pragma|PIK___pragma) | erKind | pragma direc- | | | | | tive. | +---------------+----------------------------------+-----------------+------------------+ Example:: - Callback: PragmaDirective Loc: "D:/Clang/llvm/clang-tools-extra/test/pp-trace/pp-trace-pragma.cpp:3:1" Introducer: PIK_HashPragma PragmaComment Callback PragmaComment is called when a #pragma comment directive is read. Argument descriptions: +---------------+-----------------------+------------------+------------------+ | Argument Name | Argument Value | Clang C++ Type | Description | | | Syntax | | | +---------------+-----------------------+------------------+------------------+ | Loc | "(file):(line):(col)" | SourceLocation | The location of | | | | | the directive. | +---------------+-----------------------+------------------+------------------+ | Kind | ((name)|(null)) | const Identi- | The comment kind | | | | fierInfo | symbol. | +---------------+-----------------------+------------------+------------------+ | Str | (message directive) | const | The comment mes- | | | | std::string | sage directive. | +---------------+-----------------------+------------------+------------------+ Example:: - Callback: PragmaComment Loc: "D:/Clang/llvm/clang-tools-extra/test/pp-trace/pp-trace-pragma.cpp:3:1" Kind: library Str: kernel32.lib PragmaDetectMismatch Callback PragmaDetectMismatch is called when a #pragma detect_mismatch directive is read. Argument descriptions: +---------------+-----------------------+----------------+------------------+ | Argument Name | Argument Value | Clang C++ Type | Description | | | Syntax | | | +---------------+-----------------------+----------------+------------------+ | Loc | "(file):(line):(col)" | SourceLocation | The location of | | | | | the directive. | +---------------+-----------------------+----------------+------------------+ | Name | "(name)" | const | The name. | | | | std::string | | +---------------+-----------------------+----------------+------------------+ | Value | (string) | const | The value. | | | | std::string | | +---------------+-----------------------+----------------+------------------+ Example:: - Callback: PragmaDetectMismatch Loc: "D:/Clang/llvm/clang-tools-extra/test/pp-trace/pp-trace-pragma.cpp:3:1" Name: name Value: value PragmaDebug Callback PragmaDebug is called when a #pragma clang __debug directive is read. Argument descriptions: +---------------+-----------------------+----------------+------------------+ | Argument Name | Argument Value | Clang C++ Type | Description | | | Syntax | | | +---------------+-----------------------+----------------+------------------+ | Loc | "(file):(line):(col)" | SourceLocation | The location of | | | | | the directive. | +---------------+-----------------------+----------------+------------------+ | DebugType | (string) | StringRef | Indicates type | | | | | of debug mes- | | | | | sage. | +---------------+-----------------------+----------------+------------------+ Example:: - Callback: PragmaDebug Loc: "D:/Clang/llvm/clang-tools-extra/test/pp-trace/pp-trace-pragma.cpp:3:1" DebugType: warning PragmaMessage Callback PragmaMessage is called when a #pragma message directive is read. Argument descriptions: +---------------+-----------------------+----------------+------------------+ | Argument Name | Argument Value | Clang C++ Type | Description | | | Syntax | | | +---------------+-----------------------+----------------+------------------+ | Loc | "(file):(line):(col)" | SourceLocation | The location of | | | | | the directive. | +---------------+-----------------------+----------------+------------------+ | Namespace | (name) | StringRef | The namespace of | | | | | the message di- | | | | | rective. | +---------------+-----------------------+----------------+------------------+ | Kind | (PMK_Mes- | PPCall- | The type of the | | | sage|PMK_Warn- | backs::Prag- | message direc- | | | ing|PMK_Error) | maMessageKind | tive. | +---------------+-----------------------+----------------+------------------+ | Str | (string) | StringRef | The text of the | | | | | message direc- | | | | | tive. | +---------------+-----------------------+----------------+------------------+ Example:: - Callback: PragmaMessage Loc: "D:/Clang/llvm/clang-tools-extra/test/pp-trace/pp-trace-pragma.cpp:3:1" Namespace: "GCC" Kind: PMK_Message Str: The message text. PragmaDiagnosticPush Callback PragmaDiagnosticPush is called when a #pragma gcc diagnostic push di- rective is read. Argument descriptions: +---------------+-----------------------+----------------+------------------+ | Argument Name | Argument Value | Clang C++ Type | Description | | | Syntax | | | +---------------+-----------------------+----------------+------------------+ | Loc | "(file):(line):(col)" | SourceLocation | The location of | | | | | the directive. | +---------------+-----------------------+----------------+------------------+ | Namespace | (name) | StringRef | Namespace name. | +---------------+-----------------------+----------------+------------------+ Example:: - Callback: PragmaDiagnosticPush Loc: "D:/Clang/llvm/clang-tools-extra/test/pp-trace/pp-trace-pragma.cpp:3:1" Namespace: "GCC" PragmaDiagnosticPop Callback PragmaDiagnosticPop is called when a #pragma gcc diagnostic pop direc- tive is read. Argument descriptions: +---------------+-----------------------+----------------+------------------+ | Argument Name | Argument Value | Clang C++ Type | Description | | | Syntax | | | +---------------+-----------------------+----------------+------------------+ | Loc | "(file):(line):(col)" | SourceLocation | The location of | | | | | the directive. | +---------------+-----------------------+----------------+------------------+ | Namespace | (name) | StringRef | Namespace name. | +---------------+-----------------------+----------------+------------------+ Example:: - Callback: PragmaDiagnosticPop Loc: "D:/Clang/llvm/clang-tools-extra/test/pp-trace/pp-trace-pragma.cpp:3:1" Namespace: "GCC" PragmaDiagnostic Callback PragmaDiagnostic is called when a #pragma gcc diagnostic directive is read. Argument descriptions: +---------------+-----------------------+----------------+------------------+ | Argument Name | Argument Value | Clang C++ Type | Description | | | Syntax | | | +---------------+-----------------------+----------------+------------------+ | Loc | "(file):(line):(col)" | SourceLocation | The location of | | | | | the directive. | +---------------+-----------------------+----------------+------------------+ | Namespace | (name) | StringRef | Namespace name. | +---------------+-----------------------+----------------+------------------+ | mapping | (0|MAP_IG- | diag::Severity | Mapping type. | | | NORE|MAP_WARN- | | | | | ING|MAP_ERROR|MAP_FA- | | | | | TAL) | | | +---------------+-----------------------+----------------+------------------+ | Str | (string) | StringRef | Warning/error | | | | | name. | +---------------+-----------------------+----------------+------------------+ Example:: - Callback: PragmaDiagnostic Loc: "D:/Clang/llvm/clang-tools-extra/test/pp-trace/pp-trace-pragma.cpp:3:1" Namespace: "GCC" mapping: MAP_WARNING Str: WarningName PragmaOpenCLExtension Callback PragmaOpenCLExtension is called when OpenCL extension is either dis- abled or enabled with a pragma. Argument descriptions: +---------------+-----------------------+------------------+------------------+ | Argument Name | Argument Value | Clang C++ Type | Description | | | Syntax | | | +---------------+-----------------------+------------------+------------------+ | NameLoc | "(file):(line):(col)" | SourceLocation | The location of | | | | | the name. | +---------------+-----------------------+------------------+------------------+ | Name | (name) | const Identi- | Name symbol. | | | | fierInfo | | +---------------+-----------------------+------------------+------------------+ | StateLoc | "(file):(line):(col)" | SourceLocation | The location of | | | | | the state. | +---------------+-----------------------+------------------+------------------+ | State | (1|0) | unsigned | Enabled/disabled | | | | | state. | +---------------+-----------------------+------------------+------------------+ Example:: - Callback: PragmaOpenCLExtension NameLoc: "D:/Clang/llvm/clang-tools-extra/test/pp-trace/pp-trace-pragma.cpp:3:10" Name: Name StateLoc: "D:/Clang/llvm/clang-tools-extra/test/pp-trace/pp-trace-pragma.cpp:3:18" State: 1 PragmaWarning Callback PragmaWarning is called when a #pragma warning directive is read. Argument descriptions: +---------------+-----------------------+----------------+------------------+ | Argument Name | Argument Value | Clang C++ Type | Description | | | Syntax | | | +---------------+-----------------------+----------------+------------------+ | Loc | "(file):(line):(col)" | SourceLocation | The location of | | | | | the directive. | +---------------+-----------------------+----------------+------------------+ | WarningSpec | (string) | StringRef | The warning | | | | | specifier. | +---------------+-----------------------+----------------+------------------+ | Ids | [(number)[, ...]] | ArrayRef<int> | The warning num- | | | | | bers. | +---------------+-----------------------+----------------+------------------+ Example:: - Callback: PragmaWarning Loc: "D:/Clang/llvm/clang-tools-extra/test/pp-trace/pp-trace-pragma.cpp:3:1" WarningSpec: disable Ids: 1,2,3 PragmaWarningPush Callback PragmaWarningPush is called when a #pragma warning(push) directive is read. Argument descriptions: +---------------+-----------------------+----------------+------------------+ | Argument Name | Argument Value | Clang C++ Type | Description | | | Syntax | | | +---------------+-----------------------+----------------+------------------+ | Loc | "(file):(line):(col)" | SourceLocation | The location of | | | | | the directive. | +---------------+-----------------------+----------------+------------------+ | Level | (number) | int | Warning level. | +---------------+-----------------------+----------------+------------------+ Example:: - Callback: PragmaWarningPush Loc: "D:/Clang/llvm/clang-tools-extra/test/pp-trace/pp-trace-pragma.cpp:3:1" Level: 1 PragmaWarningPop Callback PragmaWarningPop is called when a #pragma warning(pop) directive is read. Argument descriptions: +---------------+-----------------------+----------------+------------------+ | Argument Name | Argument Value | Clang C++ Type | Description | | | Syntax | | | +---------------+-----------------------+----------------+------------------+ | Loc | "(file):(line):(col)" | SourceLocation | The location of | | | | | the directive. | +---------------+-----------------------+----------------+------------------+ Example:: - Callback: PragmaWarningPop Loc: "D:/Clang/llvm/clang-tools-extra/test/pp-trace/pp-trace-pragma.cpp:3:1" MacroExpands Callback MacroExpands is called when ::HandleMacroExpandedIdentifier when a macro invocation is found. Argument descriptions: +----------------+-------------------------+------------------+------------------+ | Argument Name | Argument Value | Clang C++ Type | Description | | | Syntax | | | +----------------+-------------------------+------------------+------------------+ | MacroNameTok | (token) | const Token | The macro name | | | | | token. | +----------------+-------------------------+------------------+------------------+ | MacroDirective | (MD_De- | const MacroDi- | The kind of | | | fine|MD_Unde- | rective | macro directive | | | fine|MD_Visibil- | | from the | | | ity) | | MacroDirective | | | | | structure. | +----------------+-------------------------+------------------+------------------+ | Range | ["(file):(line):(col)", | SourceRange | The source range | | | "(file):(line):(col)"] | | for the expan- | | | | | sion. | +----------------+-------------------------+------------------+------------------+ | Args | [(name)|(number)|<(to- | const MacroArgs | The argument to- | | | ken name)>[, ...]] | | kens. Names and | | | | | numbers are lit- | | | | | eral, everything | | | | | else is of the | | | | | form '<' token- | | | | | Name '>'. | +----------------+-------------------------+------------------+------------------+ Example:: - Callback: MacroExpands MacroNameTok: X_IMPL MacroDirective: MD_Define Range: [(nonfile), (nonfile)] Args: [a <plus> y, b] MacroDefined Callback MacroDefined is called when a macro definition is seen. Argument descriptions: +----------------+------------------+------------------+------------------+ | Argument Name | Argument Value | Clang C++ Type | Description | | | Syntax | | | +----------------+------------------+------------------+------------------+ | MacroNameTok | (token) | const Token | The macro name | | | | | token. | +----------------+------------------+------------------+------------------+ | MacroDirective | (MD_De- | const MacroDi- | The kind of | | | fine|MD_Unde- | rective | macro directive | | | fine|MD_Visibil- | | from the | | | ity) | | MacroDirective | | | | | structure. | +----------------+------------------+------------------+------------------+ Example:: - Callback: MacroDefined MacroNameTok: X_IMPL MacroDirective: MD_Define MacroUndefined Callback MacroUndefined is called when a macro #undef is seen. Argument descriptions: +----------------+------------------+------------------+------------------+ | Argument Name | Argument Value | Clang C++ Type | Description | | | Syntax | | | +----------------+------------------+------------------+------------------+ | MacroNameTok | (token) | const Token | The macro name | | | | | token. | +----------------+------------------+------------------+------------------+ | MacroDirective | (MD_De- | const MacroDi- | The kind of | | | fine|MD_Unde- | rective | macro directive | | | fine|MD_Visibil- | | from the | | | ity) | | MacroDirective | | | | | structure. | +----------------+------------------+------------------+------------------+ Example:: - Callback: MacroUndefined MacroNameTok: X_IMPL MacroDirective: MD_Define Defined Callback Defined is called when the 'defined' operator is seen. Argument descriptions: +----------------+-------------------------+------------------+------------------+ | Argument Name | Argument Value | Clang C++ Type | Description | | | Syntax | | | +----------------+-------------------------+------------------+------------------+ | MacroNameTok | (token) | const Token | The macro name | | | | | token. | +----------------+-------------------------+------------------+------------------+ | MacroDirective | (MD_De- | const MacroDi- | The kind of | | | fine|MD_Unde- | rective | macro directive | | | fine|MD_Visibil- | | from the | | | ity) | | MacroDirective | | | | | structure. | +----------------+-------------------------+------------------+------------------+ | Range | ["(file):(line):(col)", | SourceRange | The source range | | | "(file):(line):(col)"] | | for the direc- | | | | | tive. | +----------------+-------------------------+------------------+------------------+ Example:: - Callback: Defined MacroNameTok: MACRO MacroDirective: (null) Range: ["D:/Clang/llvm/clang-tools-extra/test/pp-trace/pp-trace-macro.cpp:8:5", "D:/Clang/llvm/clang-tools-extra/test/pp-trace/pp-trace-macro.cpp:8:19"] SourceRangeSkipped Callback SourceRangeSkipped is called when a source range is skipped. Argument descriptions: +---------------+-------------------------+----------------+------------------+ | Argument Name | Argument Value | Clang C++ Type | Description | | | Syntax | | | +---------------+-------------------------+----------------+------------------+ | Range | ["(file):(line):(col)", | SourceRange | The source range | | | "(file):(line):(col)"] | | skipped. | +---------------+-------------------------+----------------+------------------+ Example:: - Callback: SourceRangeSkipped Range: [":/Clang/llvm/clang-tools-extra/test/pp-trace/pp-trace-macro.cpp:8:2", ":/Clang/llvm/clang-tools-extra/test/pp-trace/pp-trace-macro.cpp:9:2"] If Callback If is called when an #if is seen. Argument descriptions: +----------------+-------------------------+----------------+------------------+ | Argument Name | Argument Value | Clang C++ Type | Description | | | Syntax | | | +----------------+-------------------------+----------------+------------------+ | Loc | "(file):(line):(col)" | SourceLocation | The location of | | | | | the directive. | +----------------+-------------------------+----------------+------------------+ | ConditionRange | ["(file):(line):(col)", | SourceRange | The source range | | | "(file):(line):(col)"] | | for the condi- | | | | | tion. | +----------------+-------------------------+----------------+------------------+ | ConditionValue | (true|false) | bool | The condition | | | | | value. | +----------------+-------------------------+----------------+------------------+ Example:: - Callback: If Loc: "D:/Clang/llvm/clang-tools-extra/test/pp-trace/pp-trace-macro.cpp:8:2" ConditionRange: ["D:/Clang/llvm/clang-tools-extra/test/pp-trace/pp-trace-macro.cpp:8:4", "D:/Clang/llvm/clang-tools-extra/test/pp-trace/pp-trace-macro.cpp:9:1"] ConditionValue: false Elif Callback Elif is called when an #elif is seen. Argument descriptions: +----------------+-------------------------+----------------+------------------+ | Argument Name | Argument Value | Clang C++ Type | Description | | | Syntax | | | +----------------+-------------------------+----------------+------------------+ | Loc | "(file):(line):(col)" | SourceLocation | The location of | | | | | the directive. | +----------------+-------------------------+----------------+------------------+ | ConditionRange | ["(file):(line):(col)", | SourceRange | The source range | | | "(file):(line):(col)"] | | for the condi- | | | | | tion. | +----------------+-------------------------+----------------+------------------+ | ConditionValue | (true|false) | bool | The condition | | | | | value. | +----------------+-------------------------+----------------+------------------+ | IfLoc | "(file):(line):(col)" | SourceLocation | The location of | | | | | the directive. | +----------------+-------------------------+----------------+------------------+ Example:: - Callback: Elif Loc: "D:/Clang/llvm/clang-tools-extra/test/pp-trace/pp-trace-macro.cpp:10:2" ConditionRange: ["D:/Clang/llvm/clang-tools-extra/test/pp-trace/pp-trace-macro.cpp:10:4", "D:/Clang/llvm/clang-tools-extra/test/pp-trace/pp-trace-macro.cpp:11:1"] ConditionValue: false IfLoc: "D:/Clang/llvm/clang-tools-extra/test/pp-trace/pp-trace-macro.cpp:8:2" Ifdef Callback Ifdef is called when an #ifdef is seen. Argument descriptions: +----------------+-----------------------+------------------+------------------+ | Argument Name | Argument Value | Clang C++ Type | Description | | | Syntax | | | +----------------+-----------------------+------------------+------------------+ | Loc | "(file):(line):(col)" | SourceLocation | The location of | | | | | the directive. | +----------------+-----------------------+------------------+------------------+ | MacroNameTok | (token) | const Token | The macro name | | | | | token. | +----------------+-----------------------+------------------+------------------+ | MacroDirective | (MD_Define|MD_Unde- | const MacroDi- | The kind of | | | fine|MD_Visibility) | rective | macro directive | | | | | from the | | | | | MacroDirective | | | | | structure. | +----------------+-----------------------+------------------+------------------+ Example:: - Callback: Ifdef Loc: "D:/Clang/llvm/clang-tools-extra/test/pp-trace/pp-trace-conditional.cpp:3:1" MacroNameTok: MACRO MacroDirective: MD_Define Ifndef Callback Ifndef is called when an #ifndef is seen. Argument descriptions: +----------------+-----------------------+------------------+------------------+ | Argument Name | Argument Value | Clang C++ Type | Description | | | Syntax | | | +----------------+-----------------------+------------------+------------------+ | Loc | "(file):(line):(col)" | SourceLocation | The location of | | | | | the directive. | +----------------+-----------------------+------------------+------------------+ | MacroNameTok | (token) | const Token | The macro name | | | | | token. | +----------------+-----------------------+------------------+------------------+ | MacroDirective | (MD_Define|MD_Unde- | const MacroDi- | The kind of | | | fine|MD_Visibility) | rective | macro directive | | | | | from the | | | | | MacroDirective | | | | | structure. | +----------------+-----------------------+------------------+------------------+ Example:: - Callback: Ifndef Loc: "D:/Clang/llvm/clang-tools-extra/test/pp-trace/pp-trace-conditional.cpp:3:1" MacroNameTok: MACRO MacroDirective: MD_Define Else Callback Else is called when an #else is seen. Argument descriptions: +---------------+-----------------------+----------------+------------------+ | Argument Name | Argument Value | Clang C++ Type | Description | | | Syntax | | | +---------------+-----------------------+----------------+------------------+ | Loc | "(file):(line):(col)" | SourceLocation | The location of | | | | | the else direc- | | | | | tive. | +---------------+-----------------------+----------------+------------------+ | IfLoc | "(file):(line):(col)" | SourceLocation | The location of | | | | | the if direc- | | | | | tive. | +---------------+-----------------------+----------------+------------------+ Example:: - Callback: Else Loc: "D:/Clang/llvm/clang-tools-extra/test/pp-trace/pp-trace-macro.cpp:10:2" IfLoc: "D:/Clang/llvm/clang-tools-extra/test/pp-trace/pp-trace-macro.cpp:8:2" Endif Callback Endif is called when an #endif is seen. Argument descriptions: +---------------+-----------------------+----------------+------------------+ | Argument Name | Argument Value | Clang C++ Type | Description | | | Syntax | | | +---------------+-----------------------+----------------+------------------+ | Loc | "(file):(line):(col)" | SourceLocation | The location of | | | | | the endif direc- | | | | | tive. | +---------------+-----------------------+----------------+------------------+ | IfLoc | "(file):(line):(col)" | SourceLocation | The location of | | | | | the if direc- | | | | | tive. | +---------------+-----------------------+----------------+------------------+ Example:: - Callback: Endif Loc: "D:/Clang/llvm/clang-tools-extra/test/pp-trace/pp-trace-macro.cpp:10:2" IfLoc: "D:/Clang/llvm/clang-tools-extra/test/pp-trace/pp-trace-macro.cpp:8:2" Building pp-trace To build from source: 1. Read Getting Started with the LLVM System and Clang Tools Documenta- tion for information on getting sources for LLVM, Clang, and Clang Extra Tools. 2. Getting Started with the LLVM System and Building LLVM with CMake give directions for how to build. With sources all checked out into the right place the LLVM build will build Clang Extra Tools and their dependencies automatically. • If using CMake, you can also use the pp-trace target to build just the pp-trace tool and its dependencies. CLANG-RENAME Contents • Clang-Rename • Using Clang-Rename • Vim Integration • Emacs Integration See also: clang-rename is a C++ refactoring tool. Its purpose is to perform effi- cient renaming actions in large-scale projects such as renaming classes, functions, variables, arguments, namespaces etc. The tool is in a very early development stage, so you might encounter bugs and crashes. Submitting reports with information about how to re- produce the issue to the LLVM bugtracker will definitely help the project. If you have any ideas or suggestions, you might want to put a feature request there. Using Clang-Rename clang-rename is a LibTooling-based tool, and it's easier to work with if you set up a compile command database for your project (for an exam- ple of how to do this see How To Setup Tooling For LLVM). You can also specify compilation options on the command line after --: $ clang-rename -offset=42 -new-name=foo test.cpp -- -Imy_project/include -DMY_DEFINES ... To get an offset of a symbol in a file run $ grep -FUbo 'foo' file.cpp The tool currently supports renaming actions inside a single transla- tion unit only. It is planned to extend the tool's functionality to support multi-TU renaming actions in the future. clang-rename also aims to be easily integrated into popular text edi- tors, such as Vim and Emacs, and improve the workflow of users. Although a command line interface exists, it is highly recommended to use the text editor interface instead for better experience. You can also identify one or more symbols to be renamed by giving the fully qualified name: $ clang-rename -qualified-name=foo -new-name=bar test.cpp Renaming multiple symbols at once is supported, too. However, clang-re- name doesn't accept both -offset and -qualified-name at the same time. So, you can either specify multiple -offset or -qualified-name. $ clang-rename -offset=42 -new-name=bar1 -offset=150 -new-name=bar2 test.cpp or $ clang-rename -qualified-name=foo1 -new-name=bar1 -qualified-name=foo2 -new-name=bar2 test.cpp Alternatively, {offset | qualified-name} / new-name pairs can be put into a YAML file: --- - Offset: 42 NewName: bar1 - Offset: 150 NewName: bar2 ... or --- - QualifiedName: foo1 NewName: bar1 - QualifiedName: foo2 NewName: bar2 ... That way you can avoid spelling out all the names as command line argu- ments: $ clang-rename -input=test.yaml test.cpp clang-rename offers the following options: $ clang-rename --help USAGE: clang-rename [subcommand] [options] <source0> [... <sourceN>] OPTIONS: Generic Options: -help - Display available options (-help-hidden for more) -help-list - Display list of available options (-help-list-hidden for more) -version - Display the version of this program clang-rename common options: -export-fixes=<filename> - YAML file to store suggested fixes in. -extra-arg=<string> - Additional argument to append to the compiler command line Can be used several times. -extra-arg-before=<string> - Additional argument to prepend to the compiler command line Can be used several times. -force - Ignore nonexistent qualified names. -i - Overwrite edited <file>s. -input=<string> - YAML file to load oldname-newname pairs from. -new-name=<string> - The new name to change the symbol to. -offset=<uint> - Locates the symbol by offset as opposed to <line>:<column>. -p <string> - Build path -pl - Print the locations affected by renaming to stderr. -pn - Print the found symbol's name prior to renaming to stderr. -qualified-name=<string> - The fully qualified name of the symbol. Vim Integration You can call clang-rename directly from Vim! To set up clang-rename in- tegration for Vim see clang/tools/clang-rename/clang-rename.py. Please note that you have to save all buffers, in which the replacement will happen before running the tool. Once installed, you can point your cursor to symbols you want to re- name, press <leader>cr and type new desired name. The <leader> key is a reference to a specific key defined by the mapleader variable and is bound to backslash by default. Emacs Integration You can also use clang-rename while using Emacs! To set up clang-rename integration for Emacs see clang-rename/tool/clang-rename.el. Once installed, you can point your cursor to symbols you want to re- name, press M-X, type clang-rename and new desired name. Please note that you have to save all buffers, in which the replacement will happen before running the tool. CLANG-DOC Contents • Clang-Doc • Use • Output • Configuration • Options clang-doc is a tool for generating C and C++ documentation from source code and comments. The tool is in a very early development stage, so you might encounter bugs and crashes. Submitting reports with information about how to re- produce the issue to the LLVM bug tracker will definitely help the project. If you have any ideas or suggestions, please to put a feature request there. Use clang-doc is a LibTooling-based tool, and so requires a compile command database for your project (for an example of how to do this see How To Setup Tooling For LLVM). The tool will process a list of files by default: $ clang-doc File1.cpp File2.cpp ... FileN.cpp The tool can be also used with a compile commands database: $ clang-doc --executor=all-TUs compile_commands.json To select only a subset of files from the database, use the --filter flag: $ clang-doc --executor=all-TUs --filter=File[0-9]+.cpp compile_commands.json Output clang-doc produces a directory of documentation. One file is produced for each namespace and record in the project source code, containing all documentation (including contained functions, methods, and enums) for that item. The top-level directory is configurable through the output flag: $ clang-doc --output=output/directory/ compile_commands.json Configuration Configuration for clang-doc is currently limited to command-line op- tions. In the future, it may develop the ability to use a configura- tion file, but no such efforts are currently in progress. Options clang-doc offers the following options: $ clang-doc --help OVERVIEW: Generates documentation from source code and comments. Example usage for files without flags (default): $ clang-doc File1.cpp File2.cpp ... FileN.cpp Example usage for a project using a compile commands database: $ clang-doc --executor=all-TUs compile_commands.json USAGE: clang-doc [options] <source0> [... <sourceN>] OPTIONS: Generic Options: -help - Display available options (-help-hidden for more) -help-list - Display list of available options (-help-list-hidden for more) -version - Display the version of this program clang-doc options: --doxygen - Use only doxygen-style comments to generate docs. --extra-arg=<string> - Additional argument to append to the compiler command line Can be used several times. --extra-arg-before=<string> - Additional argument to prepend to the compiler command line Can be used several times. --format=<value> - Format for outputted docs. =yaml - Documentation in YAML format. =md - Documentation in MD format. =html - Documentation in HTML format. --ignore-map-errors - Continue if files are not mapped correctly. --output=<string> - Directory for outputting generated files. -p <string> - Build path --project-name=<string> - Name of project. --public - Document only public declarations. --repository=<string> - URL of repository that hosts code. Used for links to definition locations. --source-root=<string> - Directory where processed files are stored. Links to definition locations will only be generated if the file is in this dir. --stylesheets=<string> - CSS stylesheets to extend the default styles. The following flags should only be used if format is set to html: - repository - source-root - stylesheets The Doxygen documentation describes the internal software that makes up the tools of clang-tools-extra, not the external use of these tools. The Doxygen documentation contains no instructions about how to use the tools, only the APIs that make up the software. For usage instructions, please see the user's guide or reference manual for each tool. • Doxygen documentation NOTE: This documentation is generated directly from the source code with doxygen. Since the tools of clang-tools-extra are constantly under active development, what you're about to read is out of date! • Index • Search Page AUTHOR The Clang Team COPYRIGHT 2007-2025, The Clang Team 18 Apr 13, 2025 EXTRACLANGTOOLS(1)
NAME | EXTRA CLANG TOOLS 18.1.8 RELEASE NOTES | CLANG-TIDY | CLANG-INCLUDE-FIXER | MODULARIZE USER'S MANUAL | PP-TRACE USER'S MANUAL | CLANG-RENAME | CLANG-DOC | AUTHOR | COPYRIGHT
Want to link to this manual page? Use this URL:
<https://man.freebsd.org/cgi/man.cgi?query=extraclangtools-cheriot&sektion=1&manpath=FreeBSD+Ports+14.3.quarterly>