EXTRACLANGTOOLS(1) Extra Clang Tools EXTRACLANGTOOLS(1) (NAME) extraclangtools - (Extra Clang Tools) clang-tools-extra API Clang . EXTRA CLANG TOOLS 22.1.8 o o Extra Clang Tools 22.1.8 o o o clangd o o (Diagnostics) o Hover o (Cross-references) o (Inlay hints) o (Call hierarchy) o (Document symbols) o (Code folding) o (Code completion) o (Code actions) o C++20 Modules o o clang-doc o clang-query o clang-tidy o o o o o o include-fixer o clang-include-fixer o modularize o pp-trace o Visual Studio Clang-tidy LLVM Extra Clang Tools 22.1.8 Clang . Clang . LLVM LLVM . Clang LLVM Clang LLVM . checkout Git Clang . . Extra Clang Tools 22.1.8 Extra Clang Tools . Extra Clang Tools . o hicpp clang-tidy . . hicpp 23.x . o zircon clang-tidy . fuchsia . zircon . o IgnoreMacros StrictMode clang-tidy clang-tidy-20 . . o clang-analyzer-* clang-tidy . clang-analyzer-* CSA clang-tidy . o clang-tidy : o NamePrefixSuffixSilenceDissimilarityTreshold NamePrefixSuffixSilenceDissimilarityThreshold bugprone-easily-swappable-parameters <> o CharTypdefsToIgnore CharTypedefsToIgnore bugprone-signed-char-misuse <> o bugprone-unsafe-functions <> > CustomFunctions . > ( ) . ( .) o clang-tidy . -header-filter='.*' . -header-filter . o clang-tidy/ClangTidyModuleRegistry.h LLVM 24 . clang-tidy/ClangTidyModule.h . clangd o -std=c++latest C++23 . o (quick-fix) readability-identifier-naming . Hover o doxygen markdown o MacroContentsLimit hover o o (abbreviated function templates) (Cross-references) o "go to definition" auto o "go to definition" "deducing this" C++23 o (attributes) "go to definition" o "Find references" make_unique o "Document links" #include (Inlay hints) o (designator hints) - (CXXParenListInitExpr). o (type hints) auto (Call hierarchy) o enum o (Document symbols) o (inline friend) (Code folding) o o #pragma region (Code completion) o MacroFilter Completion (fuzzy-matching) FuzzyMatch . ExactPrefix . o "deducing this" C++23 o AngledHeaders QuotedHeaders include-cleaner . (Code actions) o Override pure virtual methods. override C++ . . ( public protected) . o "move function body out-of-line" . . C++20 o --experimental-modules-support (compilation database) o --debug-modules-builder clangd o o clangd o .gitignore clangd. clang-doc o HTML Mustache HTML. o concept typedef alias HTML. o throws HTML. o HTML. o HTML. o HTML. . o Home . . o (breadcrumb) navbar. . o USR . o (flat) . clang-query o Matcher clang-query (,) matcher . C++ . C++ ( C++ "expected expression" ). clang-tidy o check_clang_tidy.py C -std . -std c99-or-later . o clang-tidy . -header-filter='.*' . -header-filter . o clang-tidy . SystemHeaders . o clang-tidy (query based) CustomChecks . Query Based Custom Check <> o run-clang-tidy.py clang-tidy-diff.py (threads) . . o run-clang-tidy.py enable-check-profile . o -line-filter clang-tidy run-clang-tidy.py . o -quiet clang-tidy . o clang-tidy directory (crash) . o IgnoreMacros StrictMode clang-tidy clang-tidy-20 . . o run-clang-tidy.py clang-tidy-diff.py -hide-progress . o clang-analyzer-* clang-tidy . CSA clang-tidy . o clang-tidy --removed-arg Clang-Tidy . run-clang-tidy.py clang-tidy-diff.py RemovedArgs . o zircon clang-tidy . fuchsia . zircon . o clang-tidy WarningsAsErrors Checks . o abseil-unchecked-statusor-access <>. absl::StatusOr . o bugprone-derived-method-shadowing-base-method <>. () (shadow) . o bugprone-invalid-enum-default-initialization <>. ( 0) enum 0 . o cppcoreguidelines-pro-bounds-avoid-unchecked-container-access <>. operator[] STL . o google-runtime-float <>. long double (portability) . o llvm-mlir-op-builder <>. / OpBuilder::create MLIR T::create . o llvm-use-ranges <>. STL (range) LLVM llvm/ADT/STLExtras.h . o misc-override-with-different-visibility <>. (visibility) . o readability-inconsistent-ifelse-braces <>. if/else . o readability-redundant-parentheses <>. . o readability-redundant-typename <>. typename . o cert-dcl50-cpp <> modernize-avoid-variadic-functions <> . o cert-dcl58-cpp <> bugprone-std-namespace-modification <> . o cert-env33-c <> bugprone-command-processor <> . o cert-err34-c <> bugprone-unchecked-string-to-number-conversion <> . o cert-err52-cpp <> modernize-avoid-setjmp-longjmp <> . o cert-err58-cpp <> bugprone-throwing-static-initialization <> . o cert-err60-cpp <> bugprone-exception-copy-constructor-throws <>. o cert-flp30-c <> bugprone-float-loop-counter <> . o cert-mem57-cpp <> bugprone-default-operator-new-on-overaligned-type <> . o cert-msc30-c <> misc-predictable-rand <> . o cert-msc32-c <> bugprone-random-generator-seed <> . o cert-msc50-cpp <> misc-predictable-rand <> . o cert-msc51-cpp <> bugprone-random-generator-seed <> . o cert-oop57-cpp <> bugprone-raw-memory-call-on-non-trivial-type <> . o cert-oop58-cpp <> bugprone-copy-constructor-mutates-argument <> . o fuchsia-multiple-inheritance <> misc-multiple-inheritance <> . o google-build-namespaces <> misc-anonymous-namespace-in-header <> . o google-readability-casting <> modernize-avoid-c-style-cast <> . o bugprone-chained-comparison <> IgnoreMacros . o bugprone-dynamic-static-initializers <>: o (false positives) constexpr (value-dependent) . o constinit C++20. o bugprone-easily-swappable-parameters <> NamePrefixSuffixSilenceDissimilarityTreshold. o bugprone-exception-escape <>: o (lambda captures) . o . o CheckDestructors CheckMoveMemberFunctions CheckMain CheckedSwapFunctions CheckNothrowFunctions. o bugprone-infinite-loop <> (structured bindings). o bugprone-invalid-enum-default-initialization <> IgnoredEnums enum . o bugprone-macro-parentheses <> C++. o bugprone-narrowing-conversions <> C. o bugprone-not-null-terminated-result <> (fix-it) strncmp wcsncmp Windows . o bugprone-reserved-identifier <> . o bugprone-signed-char-misuse <> enum C23 signed char. o bugprone-sizeof-expression <> sizeof (dependent type). o bugprone-suspicious-include <> IgnoredRegex. o bugprone-tagged-union-member-count <> enum union std tagged union . o bugprone-throw-keyword-missing <>: o (canonical types) . o . o ( ) . o bugprone-unchecked-optional-access <>: o NullableValue::makeValue NullableValue::makeValueInplace BloombergLP::bdlb::NullableValue. o bsl::optional allocator-aware. o IgnoreValueCalls optional::value(). o IgnoreSmartPointerDereference optional UB operator* operator->. o bugprone-unhandled-self-assignment <> copy-and-swap . o bugprone-unsafe-functions <> > CustomFunctions . o bugprone-use-after-move <>: o InvalidationFunctions . o ReinitializationFunctions . o cppcoreguidelines-avoid-non-const-global-variables <> AllowThreadLocal -const thread-local . o cppcoreguidelines-init-variables <> . o cppcoreguidelines-macro-usage <> __attribute__((..)) . . o cppcoreguidelines-prefer-member-initializer <> . o cppcoreguidelines-pro-bounds-pointer-arithmetic <> AllowIncrementDecrementOperators /. o cppcoreguidelines-pro-type-member-init <> std::array IgnoreArrays true . o fuchsia-multiple-inheritance <> ( ) . o google-readability-casting <> fix-it (downcasts) void. o google-readability-todo <> TODO Google Style Guide. o llvm-prefer-isa-or-dyn-cast-in-conditionals <>: o Fix-it nested-name-specifier . o if init-statement (if (auto X = ...; ...)) . o for . o misc-const-correctness <>: o -const. o -const --. o . o misc-coroutine-hostile-raii <> AllowedCallees (safely awaitable) . o misc-header-include-cycle <>. o misc-use-internal-linkage <>: o (internal linkage) (struct class union enum). o AnalyzeFunctions AnalyzeVariables AnalyzeTypes / . o C. o modernize-avoid-c-arrays <> . o modernize-use-constraints <> enable_if std::enable_if ( boost::enable_if). o modernize-use-default-member-init <> . o modernize-use-designated-initializers <> (designated initializers) (aliased aggregate). o modernize-use-integer-sign-comparison <> fix-it C . o modernize-use-nullptr <> Windows clang-tidy . o modernize-use-override <> override . o modernize-use-ranges <> std::views::reverse std::ranges::reverse_view . o modernize-use-scoped-lock <> ( clang-tidy clangd ). o modernize-use-std-format <> . o modernize-use-std-print <> ASCII . o modernize-use-using <> (fix-its) typedef . o performance-move-const-arg <> (trivially copyable) . o performance-unnecessary-copy-initialization <> . o performance-unnecessary-value-param <> (fix-it hints) (parameter-pack) . o portability-template-virtual-member-function <> (pure virtual) . o readability-container-contains <> npos . . o readability-container-data-pointer <> (dereference) . o readability-container-size-empty <> size this empty . o readability-duplicate-include <> IgnoredFilesList ( ) include . o readability-identifier-naming <> : o . o . o constexpr . o . o readability-implicit-bool-conversion <> : o . o C99 . o bool (&& ||) C . o readability-inconsistent-declaration-parameter-name <> (variadic parameter pack) (specializations) . o readability-math-missing-parentheses <> . o readability-qualified-auto <> IgnoreAliasing (type aliases) . o readability-redundant-casting <> (explicit cast) . o readability-redundant-control-flow <> return continue . o readability-uppercase-literal-suffix <> C++23 C23 . o readability-use-concise-preprocessor-directives <> . o readability-use-std-min-max <> if then . include-fixer ... clang-include-fixer ... modularize ... pp-trace Clang-tidy Visual Studio CLANG-TIDY o Clang-Tidy o Clang-Tidy o Clang-Tidy o Clang-Tidy o Clang-Tidy Diff o : Clang-Tidy abseil-cleanup-ctad C++17 absl::Cleanup (factory function) (CTAD) . auto c1 = absl::MakeCleanup([] {}); const auto c2 = absl::MakeCleanup(std::function([] {})); absl::Cleanup c1 = [] {}; const absl::Cleanup c2 = std::function([] {}); abseil-duration-addition absl::Time . absl::Time absl::Duration . : // 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 (floating point) (integer) absl::Duration . : Duration (truncation) Duration . . : // 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 (cast) absl::Duration . : // Original - Cast from a double to an integer absl::Duration d; int i = static_cast(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(absl::ToInt64Seconds(d)); // Suggested - Use the integer conversion function directly. double x = absl::ToDoubleSeconds(d); : . absl::Trunc . abseil-duration-division absl::Duration . absl::Duration int64 (truncate) . absl::Duration : : 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); absl::FDivDuration() absl::ToDoubleSeconds() . : 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); absl::Duration . abseil-duration-factory-float (overloaded) absl::Duration . . (cast) . : // 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(10)); // Suggested - Remove the explicit cast absl::Duration d = absl::Seconds(10); abseil-duration-factory-scale absl::Duration . absl::ZeroDuration() . : // 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 absl::Duration . absl::Duration absl::Duration . : // 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); : clang-tidy ( ) . . clang-tidy . abseil-duration-unnecessary-conversion absl::Duration . : // 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; : // 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; : // 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; : absl::Duration ( ) . absl::Trunc . abseil-faster-strsplit-delimiter absl::StrSplit() absl::MaxSplits() () . . absl::ByAnyChar() . . : // 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 Abseil . (namespace) "internal" . (friend) include . Abseil . . : 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 namespace absl Abseil . namespace absl Abseil . : namespace absl { ... } . Abseil . abseil-redundant-strcat-calls absl::StrCat absl::StrCat absl::StrAppend . . . : 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 absl::StrCat() (append) std::string . absl::StrAppend() . . . a = absl::StrCat(a, b); // Use absl::StrAppend(&a, b) instead. absl::StrCat() functor . abseil-string-find-startswith std::string::find() std::string::rfind() ( std::string_view) 0 absl::StartsWith() . . starts_with C++20 . modernize-use-starts-ends-with <> . string s = "..."; if (s.find("Hello World") == 0) { /* do something */ } if (s.rfind("Hello World", 0) == 0) { /* do something */ } string s = "..."; if (absl::StartsWith(s, "Hello World")) { /* do something */ } if (absl::StartsWith(s, "Hello World")) { /* do something */ } StringLikeClasses (string-like). std::basic_string std::basic_string_view . . IncludeStyle include : llvm google. llvm . AbseilStringsMatchHeader strings/match.h Abseil. absl/strings/match.h . abseil-string-find-str-contains s.find(...) == string::npos ( ) absl::StrContains() . find() npos . << >> ::std::basic_string ::std::basic_string_view ::absl::string_view . StringLikeClasses . 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 */ } std::string s = "..."; if (!absl::StrContains(s, "Hello World")) { /* do something */ } absl::string_view a = "..."; if (absl::StrContains(a, "Hello World")) { /* do something */ } StringLikeClasses - (string-like). ::std::basic_string ::std::basic_string_view ::absl::string_view . IncludeStyle include llvm google. llvm . AbseilStringsMatchHeader strings/match.h Abseil. absl/strings/match.h . abseil-time-comparison absl::Time (integer) . : absl::Time (alignment) . absl::Time . . : // 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 absl::Time (Time) . (type) : o absl::Duration absl::Time . o absl::Time . absl::Time absl::Duration . absl::Time absl::Time absl::Duration . : 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-unchecked-statusor-access absl::StatusOr . StatusOr . StatusOr value operator* operator-> . (exceptions) (undefined behavior) . StatusOr ( ) StatusOr ok . StatusOr::ok StatusOr ok ( ) . StatusOr . : . (False negatives) . . . ( /invariants ) . (false positive) . (heuristics) : o const ( ) <#functionstability>. . (false positives) : o StatusOr <#lambdas> o (container) <#containers> o <# uncommonapi> o <#functionstability> o (cross-function) <#crossfunction>. . ok StatusOr . : void f(absl::StatusOr sor) { if (sor.ok()) { use(*sor); } } ok (semantic) (syntactic). () StatusOr ok . : void f(absl::StatusOr sor1) { if (sor1.ok()) { absl::optional sor2 = sor1; use(*sor2); } } ok ABSL_CHECK ASSERT_THAT . ok StatusOr . : void f(absl::StatusOr sor) { ABSL_DCHECK_OK(sor); use(*sor); } ok StatusOr ok . : void f(absl::StatusOr sor) { bool safe = false; if (sor.ok() && SomeOtherCondition()) { safe = true; } // ... more code... if (safe) { use(*sor); } } : void f1(absl::StatusOr sor) { use(*sor); // unsafe: it is unclear whether the status of `sor` is ok. } void f2(absl::StatusOr sor) { use(sor->member); // unsafe: it is unclear whether the status of `sor` is ok. } void f3(absl::StatusOr sor) { use(sor.value()); // unsafe: it is unclear whether the status of `sor` is ok. } ABSL_CHECK_OK OK crash () . : .value() StatusOr ok() . . StatusOr . : void f(absl::StatusOr sor) { if (sor.ok()) { } else { use(*sor); // unsafe: it is clear that the status of `sor` is *not* ok. } } . . : void f(Foo foo) { if (foo.sor().ok()) { use(*foo.sor()); // unsafe: it is unclear whether the status of `foo.sor()` is ok. } } . : void f(Foo foo) { if (const auto& foo_sor = foo.sor(); foo_sor.ok()) { use(*foo_sor); } } (accessor) const const : class Foo { const absl::StatusOr& get() const { [...]; } } void f(Foo foo) { if (foo.get().ok()) { use(*foo.get()); } } const . class Foo { const absl::StatusOr& get() const { [...]; } void mutate(); } void f(Foo foo) { if (foo.get().ok()) { foo.mutate(); use(*foo.get()); // unsafe: mutate might have changed the state of the object } } API API . : void f(Foo foo) { if (foo.HasProperty("bar")) { use(*foo.GetProperty("bar")); // unsafe: it is unclear whether the status of `foo.GetProperty("bar")` is ok. } } StatusOr (ok) . : void f(Foo foo) { if (const auto& property = foo.GetProperty("bar"); property.ok()) { use(*property); } } StatusOr . . StatusOr (ok) . : void g(absl::StatusOr sor) { use(*sor); // unsafe: it is unclear whether the status of `sor` is ok. } void f(absl::StatusOr sor) { if (sor.ok()) { g(sor); } } StatusOr . : void g(int val) { use(val); } void f(absl::StatusOr sor) { if (sor.ok()) { g(*sor); } } using StatusOr using . : using StatusOrInt = absl::StatusOr; void f(StatusOrInt sor) { use(*sor); // unsafe: it is unclear whether the status of `sor` is ok. } StatusOr . . : void f(std::vector> sors) { if (sors[0].ok()) { use(*sors[0]); // unsafe: it is unclear whether the status of `sors[0]` is ok. } } : void f(std::vector> sors) { absl::StatusOr& sor0 = sors[0]; if (sor0.ok()) { use(*sor0); } } . StatusOr . : void f(absl::StatusOr sor) { if (sor.ok()) { [&sor]() { use(*sor); // unsafe: it is unclear whether the status of `sor` is ok. } } } (capture) : void f(absl::StatusOr sor) { if (sor.ok()) { auto& s = *sor; [&s]() { use(s); } } } : void f(absl::StatusOr sor) { [&sor]() { if (sor.ok()) { use(*sor); } } } abseil-upgrade-duration-conversions (factory) absl::Duration API (explicit cast) . *= /= * / absl::Duration . int64_t std::atomic (lossy conversion) . absl::Duration ( absl::Hours absl::Minutes ) int64_t . int64_t . . . : std::atomic a; absl::Duration d = absl::Milliseconds(a); d *= a; : std::atomic a; absl::Duration d = absl::Milliseconds(static_cast(a)); d *= static_cast(a); int64_t . . altera-id-dependent-backward-branch (ID-dependent) . . // 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; } Altera SDK for OpenCL: Best Practices Guide . altera-kernel-name-restriction include kernel.cl Verilog.cl VHDL.cl . . . Guidelines for Naming the Kernel Intel FPGA SDK for OpenCL Pro Edition: Programming Guide . altera-single-work-item-barrier OpenCL (barrier) (get_local_id get_local_id get_group_id get_local_linear_id) . work-item Altera Offline Compiler ( 17.01 ) NDRange . Altera Offline Compiler work-item NDRange . Altera SDK for OpenCL: Best Practices Guide . : // 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); } AOCVersion Altera Offline Compiler . 1600 ( 16.00). altera-struct-pack-align (structs) (pack) (align) / . . (Fix-its) / (attributes) . 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 (unroll) . (kernels) OpenCL . . : o while do..while . o for (+ - * /). . o . . 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 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]++; } MaxLoopIterations . 100 . . android-cloexec-accept accept() accept4() . (file descriptor) fork+exec SELinux . : accept(sockfd, addr, addrlen); // becomes accept4(sockfd, addr, addrlen, SOCK_CLOEXEC); android-cloexec-accept4 accept4() SOCK_CLOEXEC type . fork+exec SELinux . : accept4(sockfd, addr, addrlen, SOCK_NONBLOCK); // becomes accept4(sockfd, addr, addrlen, SOCK_NONBLOCK | SOCK_CLOEXEC); android-cloexec-creat creat() open() . : int fd = creat(path, mode); // becomes int fd = open(path, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, mode); android-cloexec-dup dup() fcntl() close-on-exec . fork+exec SELinux . : int fd = dup(oldfd); // becomes int fd = fcntl(oldfd, F_DUPFD_CLOEXEC); android-cloexec-epoll-create epoll_create() epoll_create1() close-on-exec . : epoll_create(size); // becomes epoll_create1(EPOLL_CLOEXEC); android-cloexec-epoll-create1 epoll_create1() EPOLL_CLOEXEC type (file descriptor) . fork+exec SELinux . : epoll_create1(0); // becomes epoll_create1(EPOLL_CLOEXEC); android-cloexec-fopen fopen() e mode re . FD_CLOEXEC . : fopen("fn", "r"); // becomes fopen("fn", "re"); android-cloexec-inotify-init inotify_init() inotify_init1() . : inotify_init(); // becomes inotify_init1(IN_CLOEXEC); android-cloexec-inotify-init1 inotify_init1() IN_CLOEXEC type . fork+exec SELinux . : inotify_init1(IN_NONBLOCK); // becomes inotify_init1(IN_NONBLOCK | IN_CLOEXEC); android-cloexec-memfd-create memfd_create() MFD_CLOEXEC type . fork+exec SELinux . : memfd_create(name, MFD_ALLOW_SEALING); // becomes memfd_create(name, MFD_ALLOW_SEALING | MFD_CLOEXEC); android-cloexec-open O_CLOEXEC . fork+exec SELinux . open() openat() open64() O_CLOEXEC flags . : 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 pipe() . pipe() pipe2() . O_CLOEXEC (file descriptor) . SELinux . : pipe(pipefd); : pipe2(pipefd, O_CLOEXEC); android-cloexec-pipe2 pipe2() O_CLOEXEC . O_CLOEXEC . SELinux . : pipe2(pipefd, O_NONBLOCK); : pipe2(pipefd, O_NONBLOCK | O_CLOEXEC); android-cloexec-socket socket() SOCK_CLOEXEC type . fork+exec SELinux . : socket(domain, type, SOCK_STREAM); // becomes socket(domain, type, SOCK_STREAM | SOCK_CLOEXEC); android-comparison-in-temp-failure-retry TEMP_FAILURE_RETRY . TEMP_FAILURE_RETRY . TEMP_FAILURE_RETRY glibc Bionic . (syscall) (interrupted) . : char cs[1]; while (TEMP_FAILURE_RETRY(read(STDIN_FILENO, cs, sizeof(cs)) != 0)) { // Do something with cs. } TEMP_FAILURE_RETRY -1 . : TEMP_FAILURE_RETRY : char cs[1]; while (TEMP_FAILURE_RETRY(read(STDIN_FILENO, cs, sizeof(cs))) != 0) { // Do something with cs. } RetryMacros (retry) . TEMP_FAILURE_RETRY . boost-use-ranges (iterator) Boost (Boost ranges) . auto Iter1 = std::find(Items.begin(), Items.end(), 0); auto AreSame = std::equal(Items1.cbegin(), Items1.cend(), std::begin(Items2), std::end(Items2)); : auto Iter1 = boost::range::find(Items, 0); auto AreSame = boost::range::equal(Items1, Items2); std : std::accumulate, std::adjacent_difference, std::adjacent_find, std::all_of, std::any_of, std::binary_search, std::copy_backward, std::copy_if, std::copy, std::count_if, std::count, std::equal_range, std::equal, std::fill, std::find_end, std::find_first_of, std::find_if_not, std::find_if, std::find, std::for_each, std::generate, std::includes, std::iota, std::is_partitioned, std::is_permutation, std::is_sorted_until, std::is_sorted, std::lexicographical_compare, std::lower_bound, std::make_heap, std::max_element, std::merge, std::min_element, std::mismatch, std::next_permutation, std::none_of, std::partial_sum, std::partial_sort_copy, std::partition_copy, std::partition_point, std::partition, std::pop_heap, std::prev_permutation, std::push_heap, std::random_shuffle, std::reduce, std::remove_copy_if, std::remove_copy, std::remove_if, std::remove, std::replace_copy_if, std::replace_copy, std::replace_if, std::replace, std::reverse_copy, std::reverse, std::search, std::set_difference, std::set_intersection, std::set_symmetric_difference, std::set_union, std::sort_heap, std::sort, std::stable_partition, std::stable_sort, std::transform, std::unique_copy, std::unique, std::upper_bound. (namespace) boost::algorithm : all_of_equal, any_of_equal, any_of, apply_permutation, apply_reverse_permutation, clamp_range, copy_if_until, copy_if_while, copy_if, copy_until, copy_while, find_backward, find_if_backward, find_if_not_backward, find_if_not, find_not_backward, hex_lower, hex, iota, all_of, is_decreasing, is_increasing, is_palindrome, is_partitioned_until, is_partitioned, is_permutation, is_sorted_until, is_sorted, is_strictly_decreasing, is_strictly_increasing, none_of_equal, none_of, one_of_equal, one_of, partition_copy, partition_point, reduce, unhex. (Reverse Iteration) (reverse iterators) boost::adaptors::reverse . auto AreSame = std::equal(Items1.rbegin(), Items1.rend(), std::crbegin(Items2), std::crend(Items2)); : auto AreSame = boost::range::equal(boost::adaptors::reverse(Items1), boost::adaptors::reverse(Items2)); IncludeStyle include llvm google. llvm . IncludeBoostSystem true ( ) boost (#include ) (#include "boost.hpp"). UseReversePipe true ( false ) (pipe) . std::find(Items.rbegin(), Items.rend(), 0); : boost::range::find(Items | boost::adaptors::reversed, 0); boost-use-to-string int std::string std::wstring boost::lexical_cast std::to_string std::to_wstring . to_string (floating points) . auto str = boost::lexical_cast(42); auto wstr = boost::lexical_cast(2137LL); // Will be changed to auto str = std::to_string(42); auto wstr = std::to_wstring(2137LL); bugprone-argument-comment . /*parameter_name=*/ . void f(bool foo); ... f(/*bar=*/true); // warning: argument name 'bar' in comment does not match parameter name 'foo' ..SS StrictMode false (underscore) -- . false . IgnoreSingleArgument true . false . CommentBoolLiterals true /*ParameterName=*/ . false . : void foo(bool TurnKey, bool PressButton); foo(true, false); : void foo(bool TurnKey, bool PressButton); foo(/*TurnKey=*/true, /*PressButton=*/false); CommentIntegerLiterals true /*ParameterName=*/ . false . : void foo(int MeaningOfLife); foo(42); : void foo(int MeaningOfLife); foo(/*MeaningOfLife=*/42); CommentFloatLiterals true /*ParameterName=*/ float/double . false . : void foo(float Pi); foo(3.14159); : void foo(float Pi); foo(/*Pi=*/3.14159); CommentStringLiterals true /*ParameterName=*/ . false . : void foo(const char *String); void foo(const wchar_t *WideString); foo("Hello World"); foo(L"Hello World"); : void foo(const char *String); void foo(const wchar_t *WideString); foo(/*String=*/"Hello World"); foo(/*WideString=*/L"Hello World"); CommentCharacterLiterals true /*ParameterName=*/ . false . : void foo(char *Character); foo('A'); : void foo(char *Character); foo(/*Character=*/'A'); CommentUserDefinedLiterals true /*ParameterName=*/ . false . : void foo(double Distance); double operator"" _km(long double); foo(402.0_km); : void foo(double Distance); double operator"" _km(long double); foo(/*Distance=*/402.0_km); CommentNullPtrs true /*ParameterName=*/ nullptr . false . : void foo(A* Value); foo(nullptr); : void foo(A* Value); foo(/*Value=*/nullptr); bugprone-assert-side-effect assert() (side effect) . assert() (debug) debug release . AssertMacros assert . assert,NSAssert,NSCAssert . CheckFunctionCalls -const . . IgnoredFunctions () . (regex) [Rr]ef(erence)?$ Ref ref Reference reference . . :: ( namespace::Type) ( Type) . bugprone-assignment-in-if-condition (assignments) if . . if -Wparentheses operator=() . <> BARR . 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 pthread_kill SIGTERM . SIGTERM . pthread_kill(thread, SIGTERM); CERT C POS44-C. Do not use signals to terminate threads . cert-pos44-c . bugprone-bitwise-pointer-cast std::bit_cast memcpy (cast) . std::bit_cast reinterpret_cast C++ . reinterpret_cast std::bit_cast : int x{}; -float y = *reinterpret_cast(&x); +float y = *std::bit_cast(&x); reinterpret_cast (Undefined Behavior) . std::bit_cast ( ) strict aliasing . <<>> std::bit_cast . std::bit_cast (value types) : int x{}; float y = std::bit_cast(x); . To . reinterpret_cast . C++20 std::bit_cast memcpy memcpy . : int* x{}; float* y{}; std::memcpy(&y, &x, sizeof(x)); reinterpret_cast . bugprone-bool-pointer-implicit-conversion (implicit conversion) bool bool . : bool *p; if (p) { // Never used in a pointer-specific way. } bugprone-branch-clone ' ' if/else if/else ' switch ' true false '. if (test_value(x)) { y++; do_something(x, y); } else { y++; do_something(x, y); } ( ' - ) ' then else : test_value(x); // can be omitted unless it has side effects y++; do_something(x, y); ' '. ' ' if/else if/else ' . if - '. if if . : void test_warn_inner_if_1(int x) { if (x == 1) { // warns, if with identical inner if if (x == 1) // inner if is here ; if (x == 1) { // does not warn, cannot detect int y = x; if (x == 1) ; } } switch ' ' case: . : switch (ch) { case 'a': return 10; case 'A': return 10; case 'b': return 11; case 'B': return 11; default: return 10; } ' ' 'a' 'A' ( ' 'b' 'B' ) ' default: . ' : switch (ch) { case 'a': case 'A': return 10; case 'b': case 'B': return 11; default: return 10; } return 10; ' 'a' 'b' default: . switch [[fallthrough]] . ': return test_value(x) ? x : x; if '. : ' '. bugprone-capturing-this-in-member-variable (lambda captures) this (copy/move constructors) . this . (move) this . this . struct C { C() : Captured([this]() -> C const * { return this; }) {} std::function Captured; }; void foo() { C v1{}; C v2 = v1; // v2.Captured capture v1's 'this' pointer assert(v2.Captured() == v1.Captured()); // v2.Captured capture v1's 'this' pointer assert(v2.Captured() == &v2); // assertion failed. } : o (deleted). o (function object). o this . FunctionWrapperTypes (semicolon) . (function wrapper) . ::std::function;::std::move_only_function;::boost::function. BindFunctions (fully qualified) this (capture) . ::std::bind;::boost::bind;::std::bind_front;::std::bind_back; ::boost::compat::bind_front;::boost::compat::bind_back. bugprone-casting-through-void (cast) void* C++ reinterpret_cast . void* . o . o (pointer alignment) . strict aliasing (undefined behavior) . o (multiple inheritance) . void* . reinterpret_cast . : reinterpret_cast cppcoreguidelines-pro-type-reinterpret-cast <> . : reinterpret_cast strict aliasing (dereferencing) (Undefined Behavior) . reinterpret_cast (suppress ). : using IntegerPointer = int *; double *ptr; static_cast(static_cast(ptr)); // WRONG reinterpret_cast(reinterpret_cast(ptr)); // WRONG (IntegerPointer)(void *)ptr; // WRONG IntegerPointer(static_cast(ptr)); // WRONG reinterpret_cast(ptr); // OK, clearly expresses intent. // NOTE: dereferencing this pointer violates // the strict aliasing rules, invoking // Undefined Behavior. bugprone-chained-comparison . . a < b < c a b c . (a < b) && (b < c) . (a < b) < c a b c . . : int a = 2, b = 6, c = 4; if (a < b < c) { // This block will be executed } a b b c . a < b < c (a < b) < c . a < b true (a < b) < c 1 < c true < c b < c false . int bool : bool a = false, b = false, c = true; if (a == b == c) { // This block will be executed } a b c . a == b == c (a == b) == c . a == b (true) (a == b) == c true == c true == true . true a b false c . : if (a == b && b == c) { // This block will not be executed } . if ((a == b) == c) { // This block will be executed } IgnoreMacros true . false . bugprone-command-processor system() popen() _popen() (command processor) . system() null . CERT C : ENV33-C. Do not call system() . bugprone-compare-pointer-to-member-virtual-function (unspecified behavior) (null-pointer-constant) . 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. } null . (vtable) . . (pure virtual) . typeid . . nullptr . . class struct . bugprone-copy-constructor-init (copy constructors) . class Copyable { public: Copyable() = default; Copyable(const Copyable &) = default; int memberToBeCopied = 0; }; class X2 : public Copyable { X2(const X2 &other) {} // Copyable(other) is missing }; . class X3 : public Copyable { X3(const X3 &other) : Copyable() {} // other is missing }; (sub-objects) (undefined behavior) . . o ( ) . o private deleted . o (non-default) . (fix-its) . bugprone-copy-constructor-mutates-argument . CERT C : OOP58-CPP. Copy operations must not mutate the source object . bugprone-crtp-constructor-accessibility (Curiously Recurring Template Pattern CRTP) CRTP . CRTP . . : template class CRTP { private: CRTP() = default; friend T; }; class Derived : CRTP {}; . CRTP public . : template class CRTP { public: CRTP() = default; }; class Good : CRTP {}; Good GoodInstance; CRTP BadInstance; protected . : template class CRTP { protected: CRTP() = default; }; class Good : CRTP {}; Good GoodInstance; class Bad : CRTP {}; Bad BadInstance; private friend . (private) CRTP . (deleted) public protected . : template class CRTP { CRTP() = default; friend T; }; class Good : CRTP {}; Good GoodInstance; class Bad : CRTP {}; Bad CompileTimeError; CRTP AlsoCompileTimeError; o C++11 o (variadic template) o CRTP (factory functions) (fix-its) . bugprone-dangling-handle (dangling references) std::string_view . . : string_view View = string(); // View will dangle. string A; View = A + "A"; // still dangle. vector 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; } span g() { array V; return {V}; int Array[10]{}; return {Array}; } HandleClasses - . std::basic_string_view std::experimental::basic_string_view std::span . bugprone-default-operator-new-on-overaligned-type operator new ( / fundamental alignment) . operator new . ( ) operator new placement new ( ). MEM57-CPP CERT C++ : Avoid using default operator new for over-aligned types . bugprone-derived-method-shadowing-base-method ( ) (shadow) . <<>> (shadowing) ( ). (public) (non-templated) . Derived reset Derived Base::reset() . : o (polymorphic) reset o Derived::reset Base::reset o using Base::reset (access specifier) (Liskov Substitution Principle) . struct Base { void reset() {/* reset the base class */}; }; struct Derived : public Base { void reset() {/* reset the derived class, but not the base class */}; }; bugprone-dynamic-static-initializers (static) . . ( -fno-threadsafe-statics) (race conditions) . . : int foo() { static int k = bar(); return k; } foo k . bugprone-easily-swappable-parameters ( ) . void drawPoint(int X, int Y) { /* ... */ } FILE *open(const char *Dir, const char *Name, Flags Mode) { /* ... */ } drawPoint(-2, 5) openPath("a.txt", "tmp", Read) . (type-safe) opaque typedef (strong types) . struct Coord2D { int X; int Y; }; void drawPoint(const Coord2D Pos) { /* ... */ } FILE *open(const Path &Dir, const Filename &Name, Flags Mode) { /* ... */ } (refactoring) API (fix-its) . / ( ) . . . QualifiersMix cvr-qualified T cvr-qualified ( T const T const T volatile T ) . false . True . false . QualifiersMix : void *memcpy(const void *Destination, void *Source, std::size_t N) { /* ... */ } ModelImplicitConversions T U (implicit conversion) T U U T . false . True . true . ModelImplicitConversions : void fun(int Int, double Double) { /* ... */ } void compare(const char *CharBuf, std::string String) { /* ... */ } : ( int const int) C++ implicit conversion . QualifiersMix . QualifiersMix ModelImplicitConversions : void fun2(int Int, const double Double) { /* ... */ } (). MinimumLength . 2 . 2 . 0 1 2 . 3 . IgnoredParameterNames . ; . "" ( !). ! : "" ( ) iterator begin end first last lhs rhs. IgnoredParameterTypeSuffixes . . ; . ! : bool It Iterator InputIt ForwardIt BidirIt RandomIt random_iterator ReverseIt reverse_iterator reverse_const_iterator RandomIt random_iterator ReverseIt reverse_iterator reverse_const_iterator Const_Iterator ConstIterator const_reverse_iterator ConstReverseIterator. _Bool ( _bool) . SuppressParametersUsedTogether . true . false (heuristics) . : o f(a, b) a < b. o (overload) . f(a, 1) f(b, 2) f(T, int). : (path-sensitive) << >> . << >> . o a.foo() b.foo(). o return . NamePrefixSuffixSilenceDissimilarityThreshold . 1 . . 0 . . LHS RHS : L R HS . text1, text2, text3 . 1 . (function signatures) ! . (variadic) C C++ . " " . C++ (explicit specializations) . (diagnostic) : int printf(const char *Format, ...) { /* ... */ } int someOldCFunction() { /* ... */ } template 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', but that's not a user-defined function. } . template 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::element_type B) { /* ... */ } // Diagnosed: The two parameter types are exactly the same. template void exact(typename Vector::element_type A, typename Vector::element_type B) { /* ... */ } // Skipped: The two parameters are both 'T' but we cannot prove this // without actually instantiating. template void falseNegative(T A, typename Vector::element_type B) { /* ... */ } ( ModelImplicitConversions ) . . strs() ( ) . 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 catch . try { // Some code that can throw an exception } catch(const std::exception&) { } catch . catch . catch . catch "" (swallowing) . . : o : . . o m : (null pointer dereferences). . o : catch . . o : . . . (propagating) . (log) . catch . . : 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; } (re-thrown) . : try { // Some code that can throw an exception } catch (const std::exception& ex) { // Re-throw the exception throw; } . try/catch . : 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; } } catch . API . try-catch . : // 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(); } catch . . IgnoreCatchWithKeywords catch . catch ( ) (semicolon) catch . : @TODO;@FIXME. AllowEmptyCatchForExceptions catch . catch . catch . . catch . : . bugprone-exception-copy-constructor-throws (copy constructor) . C++ (copy constructible) . (stack unwinding) . ( ) std::terminate . class SomeException { public: SomeException() = default; SomeException(const SomeException&) { /* may throw */ } }; void f() { throw SomeException(); // warning: thrown exception type's copy constructor can throw } CERT C++ ERR60-CPP : Exception objects must be nothrow copy constructible . bugprone-exception-escape . : o (Destructors) o (Move constructors) o (Move assignment operators) o main() o swap() o iter_swap() o iter_move() o throw() noexcept o (undefined behavior) . . swap() . swap() . main() . noexcept(false) throw(exception) swap() main() . ! . CheckDestructors true . true . CheckMoveMemberFunctions true . true . CheckMain true main() . true . CheckNothrowFunctions true noexcept throw() . true . CheckedSwapFunctions swap . swap,iter_swap,iter_move . FunctionsThatShouldNotThrow . WinMain WinMain() Windows API . . IgnoredExceptions . . bugprone-float-loop-counter for (induction expression) (floating-point) . CERT C FLP30-C : Do not use floating-point variables as loop counters . bugprone-fold-init-type std::accumulate . std::accumulate operator+ (fold) . : o (Truncation): int operator+ 0 . auto a = {0.5f, 0.5f, 0.5f, 0.5f}; return std::accumulate(std::begin(a), std::end(a), 0); o (Overflow): 0 . auto a = {65536LL * 65536 * 65536}; return std::accumulate(std::begin(a), std::end(a), 0); bugprone-forward-declaration-namespace (forward declaration) (namespace) . / . 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::' . bugprone-forwarding-reference-overload (perfect forwarding) (copy) (move) (hide) . lvalue const const perfect forwarding . : Scott Meyers, Effective Modern C++, . : class Person { public: // C1: perfect forwarding ctor template explicit Person(T&& n) {} // C2: perfect forwarding ctor with parameter default value template explicit Person(T&& n, int x = 1) {} // C3: perfect forwarding ctor guarded with enable_if template, void>> explicit Person(T&& n) {} // C4: variadic perfect forwarding ctor guarded with enable_if template, A&&...>, int> = 0> explicit Person(A&&... a) {} // C5: perfect forwarding ctor guarded with requires expression template requires requires { is_special; } explicit Person(T&& n) {} // C6: perfect forwarding ctor guarded with concept requirement template explicit Person(T&& n) {} // (possibly compiler generated) copy ctor Person(const Person& rhs); }; C1 C2 . ( private) perfect forwarding . C3-C6 enable_if concept . Background enable_if (literal) . std::enable_if std::enable_if_t . bugprone-implicit-widening-of-multiplication-result (widen) ( fix-it) . . : 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; } } } width * height (overflow) base (wrap back ). ( ) <<>> . UseCXXStaticCastsInCppSources (fix-it) C++ C++ static_cast<>() C. : true. UseCXXHeadersInCppSources C++ . : true. IgnoreConstantIntExpr ( constexpr) . . : false. : 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 erase() . remove() (container) (iterator) . erase() . (overload) . : std::vector xs; ... xs.erase(std::remove(xs.begin(), xs.end(), 10)); erase() : std::vector xs; ... xs.erase(std::remove(xs.begin(), xs.end(), 10), xs.end()); bugprone-inc-dec-in-conditions / . . . . && || . : int i = 0; // ... if (i++ < 5 && i > 0) { // do something } . i i i > 0 . . . i . i . int i = 0; // ... i++; if (i <= 5 && i > 0) { // do something } . : int i = 4; // ... if (i++ < 5 || --i > 2) { // do something } C++ . || true . i 4 i < 5 true i > 2 . --i i 5 . i . bugprone-incorrect-enable-if std::enable_if type . C++11 std::enable_if SFINAE . std::enable_if typename std::enable_if::type . type . std::enable_if . template ::type> void valid_usage() { ... } template > 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 > void invalid_usage() { ... } // The tool suggests the following replacement for 'invalid_usage': template ::type> void fixed_invalid_usage() { ... } C++14 std::enable_if_t . C++20 (constraints) std::enable_if . std::enable_if std::enable_if_t modernize-type-traits <> std::enable_if C++20 modernize-use-constraints <> . . bugprone-incorrect-enable-shared-from-this (public) std::enable_shared_from_this shared_from_this . : #include // private inheritance class BadExample : std::enable_shared_from_this { // ``shared_from_this``` unintended behaviour // `libstdc++` implementation returns uninitialized ``weak_ptr`` public: BadExample* foo() { return shared_from_this().get(); } void bar() { return; } }; void using_not_public() { auto bad_example = std::make_shared(); auto* b_ex = bad_example->foo(); b_ex->bar(); } libstdc++ shared_from_this std::bad_weak_ptr . using_not_public() . bugprone-incorrect-roundings . : (int)(double_expression + 0.5) (double) . : 1. . 2. . 0.499999975 ( 0.5) 1.0 . -0.5f -1.4f 0.0 . bugprone-infinite-loop ( ). ( Halting Problem). . . (break continue goto return throw [[noreturn]]) : o . o (reference) (pointer) . o (structure) . . i : int i = 0, j = 0; while (i < 10) { ++j; } bugprone-integer-division (floating point) . : o bool o bool o (explicit cast) bool . : 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-invalid-enum-default-initialization ( 0) enum 0 . ++C (initializer list) . 0 . 0 . enum ( ). enum ( ) enum 0 . enum (scoped) (non-scoped) . (unions) ( ). enum std::errc 0 . enum class Enum1: int { A = 1, B }; enum class Enum0: int { A = 0, B }; void f() { Enum1 X1{}; // warn: 'X1' is initialized to 0 Enum1 X2 = Enum1(); // warn: 'X2' is initialized to 0 Enum1 X3; // no warning: 'X3' is not initialized Enum0 X4{}; // no warning: type has an enumerator with value of 0 } struct S1 { Enum1 A; S(): A() {} // warn: 'A' is initialized to 0 }; struct S2 { int A; Enum1 B; }; S2 VarS2{}; // warn: member 'B' is initialized to 0 C . ( enum ) 0 . enum Enum1 { Enum1_A = 1, Enum1_B }; struct Struct1 { int a; enum Enum1 b; }; enum Enum1 Array1[2] = {Enum1_A}; // warn: omitted elements are initialized to 0 enum Enum1 Array2[2][2] = {{Enum1_A}, {Enum1_A}}; // warn: last element of both nested arrays is initialized to 0 enum Enum1 Array3[2][2] = {{Enum1_A, Enum1_A}}; // warn: elements of second array are initialized to 0 struct Struct1 S1 = {1}; // warn: element 'b' is initialized to 0 IgnoredEnums (regex) - enum . ::std::errc . bugprone-lambda-function-name (lambda) . operator() . : void FancyFunction() { [] { printf("Called from %s\n", __func__); }(); [] { printf("Now called from %s\n", __FUNCTION__); }(); } : Called from operator() Now called from operator() : Called from FancyFunction Now called from FancyFunction IgnoreMacros true . false . bugprone-macro-parentheses . . . . . . . PRE02-C CERT C . : bugprone-macro-repeated-side-effects (side effects) . bugprone-misleading-setter-of-reference setter (reference) . dereference . setter ( ) ( ) . : class MyClass { int &InternalRef; // non-const reference member public: MyClass(int &Value) : InternalRef(Value) {} // Warning: This setter could lead to unintended behaviour. void setRef(int *Value) { InternalRef = *Value; // This assigns to the referenced value, not changing what InternalRef references. } }; int main() { int Value1 = 42; int Value2 = 100; MyClass X(Value1); // This might look like it changes what InternalRef references to, // but it actually modifies Value1 to be 100. X.setRef(&Value2); } : o "set" ( const reference). o "set" ( dereference). bugprone-misplaced-operator-in-strlen-in-alloc 1 strlen() strnlen() strnlen_s() wcslen() wcsnlen() wcsnlen_s() (malloc() calloc() realloc() alloca()) new[] C++ . ( new[]) . 1 -strlen() . C: void bad_malloc(char *str) { char *c = (char*) malloc(strlen(str + 1)); } 1 strlen() . char *c = (char*) malloc(strlen(str) + 1); C++: void bad_new(char *str) { char *c = new char[strlen(str + 1)]; } C malloc() 1 strlen() . char *c = new char[strlen(str) + 1]; (silence) : void bad_malloc(char *str) { char *c = (char*) malloc(strlen((str + 1))); } bugprone-misplaced-pointer-arithmetic-in-alloc (malloc() calloc() realloc() alloca()) . . : void bad_malloc(int n) { char *p = (char*) malloc(n) + 10; } malloc . : char *p = (char*) malloc(n + 10); bugprone-misplaced-widening-cast (cast) . . . : long f(int x) { return (long)(x * 1000); } x * 1000 int . int . long . int . : long f(int x) { return (long)x * 1000; } Implicit casts . CheckImplicitCasts : long f(int x) { return x * 1000; } Floating point . : double f(float x) { return (double)(x * 10.0f); } Options CheckImplicitCasts true (implicit casts) . false . bugprone-move-forwarding-reference std::move (forwarding reference) : template void foo(T&& t) { bar(std::move(t)); } (forwarding references) std::move std::forward . ( rvalue .) : bar(std::forward(t)); Background T&& T rvalue lvalue foo() . . : std::string s = "Hello, world"; foo(s); foo() s (indeterminate state) (moved from). foo() foo() std::move . foo() -- rvalue . ( [temp.deduct.call]/3 C++11 .) foo() lvalue ( ) T lvalue . T std::string & . t std::string& && (reference collapsing) std::string& . foo(s) s lvalue foo() move s . bugprone-multi-level-implicit-pointer-conversion (indirection) . (undefined behavior) (cast) . int (int**) void* . cast dereference (access violation) (memory corruption) . : 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; } foo() ptr_ptr . ptr_ptr int** foo() void* . foo() int* dereference . (explicit cast) . . . EnableInC true C ( C++ ). true . bugprone-multiple-new-in-one-expression new (exception) new (leak) . C++ . (exception handler) . new . operator new . (short-circuit) || && , . (list-initialization { }) . ? . new new ( () ) . new . new catch std::bad_alloc std::exception . || && , ? ( ) . . (self-destructing) . : 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 . . : #define INCREMENT_TWO(x, y) (x)++; (y)++ if (do_increment) INCREMENT_TWO(a, b); // (b)++ will be executed unconditionally. cppcoreguidelines-narrowing-conversions . (narrowing conversions) : int i = 0; i += 0.1;. : void MyClass::f(double d) { int_member_ += d; }. : o ( char unsigned char) WarnOnIntegerNarrowingConversion o ( uint64_t float) WarnOnIntegerToFloatingPointNarrowingConversion o ( double int) o ( double float) WarnOnFloatingPointNarrowingConversion . : o ( c static_cast) . : int i = 0; i += 0.1; void f(int); f(0.1); o . : int i; i+= 0.1;. int (implicit conversions) "Integral Promotion" cppreference.com . -Wconversion . . // The following function definition demonstrates usage of arithmetic with // integer types smaller than `int` and how the narrowing conversion happens // implicitly. void computation(short argument1, short argument2) { // Arithmetic written by humans: short result = argument1 + argument2; // Arithmetic actually performed by C++: short result = static_cast(static_cast(argument1) + static_cast(argument2)); } void recommended_resolution(short argument1, short argument2) { short result = argument1 + argument2; // ^ warning: narrowing conversion from 'int' to signed type 'short' is implementation-defined // The cppcoreguidelines recommend to resolve this issue by using the GSL // in one of two ways. Either by a cast that throws if a loss of precision // would occur. short result = gsl::narrow(argument1 + argument2); // Or it can be resolved without checking the result risking invalid results. short result = gsl::narrow_cast(argument1 + argument2); // A classical `static_cast` will silence the warning as well if the GSL // is not available. short result = static_cast(argument1 + argument2); } (Options) WarnOnIntegerNarrowingConversion (true) ( int size_t). true . WarnOnIntegerToFloatingPointNarrowingConversion (true) ( size_t double). true . WarnOnFloatingPointNarrowingConversion (true) ( double float). true . WarnWithinTemplateInstantiation (true) (template instantiations) . false . WarnOnEquivalentBitWidth (true) . ( int n = uint(0); long long n = double(0);). true . IgnoreConversionFromTypes - . int n = std::vector().size(); int n = std::difference(it1, it2); . size_t;ptrdiff_t;size_type;difference_type . PedanticMode (true) ( int i = 1.0;). false . (FAQ) o "narrowing conversion from 'int' to 'float'" IEEE754 [-2^PrecisionBits, 2^PrecisionBits] PrecisionBits . float [-2^23, 2^23] int [-2^31, 2^31-1] . o "implementation-defined" "narrowing conversion from 'unsigned int' to signed type 'int' is implementation-defined" . C/C++ (two's complement) . Clang . bugprone-no-escape noescape (asynchronously-executed) (capture) . dispatch_async() dispatch_after() (escape) noescape . noescape . void foo(__attribute__((noescape)) int *p) { dispatch_async(queue, ^{ *p = 123; }); }); bugprone-non-zero-enum-to-bool-conversion (cast) enum bool enum . enum bool true . . enum ( ) (false positive) . // NOLINT bool . . C++11 . . 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" } EnumIgnoreList enum / bool . - enum ( fully qualified) enum . enum . bugprone-nondeterministic-pointer-iteration-order (nondeterministic) (unordered containers) . . { int a = 1, b = 2; std::unordered_set UnorderedPtrSet = {&a, &b}; for (auto i : UnorderedPtrSet) f(i); } . { int a = 1, b = 2; std::vector VectorOfPtr = {&a, &b}; std::sort(VectorOfPtr.begin(), VectorOfPtr.end()); } . . . for (range-based for loops) set map unordered . . (false negative) . o (bugprone) . o std::reference_wrapper . o for (iterators) . bugprone-not-null-terminated-result (not null-terminated) . strlen(src) + 1 . (undefined behavior) . wchar_t : memcpy, memcpy_s, memchr, memmove, memmove_s, strerror_s, strncmp, strxfrm size_t length . . static char *stringCpy(const std::string &str) { char *result = reinterpret_cast(malloc(str.size())); memcpy(result, str.data(), str.size()); return result; } (fix-it) . : static char *stringCpy(const std::string &str) { char *result = reinterpret_cast(malloc(str.size() + 1)); strcpy(result, str.data()); return result; } : (path-sensitive) . 'memcpy()' memcpy() memcpy_s() : strcpy() strncpy() strcpy_s() strncpy_s() . wchar_t . o [1] ( cpy) . o [1] WantToUseSafeFunctions true ( cpy_s) . o ++C char/wchar_t un/signed . o un/signed char */wchar_t * (cast) . [1] : o . o . o strlen(source) ( cpy) ( cpy_s) . o 'N' ncpy 'N' . 'strlen()' wchar_t ( strerror_s wchar_t ). memcpy 'memcpy()' . memchr C-style cast strchr . . memmove memmove_s . . memmove_s . strerror_s . strncmp length + 1 + 1 . strxfrm . WantToUseSafeFunctions true '_s' ( 'memcpy_s()'). true . bugprone-optional-value-conversion (optional-like) . (refactoring) . : #include void print(std::optional); int main() { std::optional opt; // ... // Unintentional conversion from std::optional to int and back to // std::optional: print(opt.value()); // ... } opt print : #include void print(std::optional); int main() { std::optional opt; // ... // Proposed code: Directly pass the std::optional to the print // function. print(opt); // ... } opt print . operator * . boost::optional absl::optional . : OptionalTypes (semicolon) (fully qualified) . ::std::optional;::absl::optional;::boost::optional . ValueMethods (semicolon) . ::value$;::get$ . bugprone-parent-virtual-call -...- (overridden) . 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-pointer-arithmetic-on-polymorphic-object (pointer arithmetic) . (polymorphic) (static type) (dynamic type) (undefined behavior) (vtable) . (heuristic) . : struct Base { virtual ~Base(); int i; }; struct Derived : public Base {}; void foo(Base* b) { b += 1; // warning: pointer arithmetic on class that declares a virtual function can // result in undefined behavior if the dynamic type differs from the // pointer type } int bar(const Derived d[]) { return d[1].i; // warning due to pointer arithmetic on polymorphic object } // Making Derived final suppresses the warning struct FinalDerived final : public Base {}; int baz(const FinalDerived d[]) { return d[1].i; // no warning as FinalDerived is final } IgnoreInheritedVirtualFunctions true . (false positives) . : false . void bar(Base b[], Derived d[]) { b += 1; // warning, as Base declares a virtual destructor d += 1; // warning only if IgnoreVirtualDeclarationsOnly is set to false } SEI Cert CTR56-CPP : Do not use pointer arithmetic on polymorphic objects . bugprone-posix-return pthread_* posix_* ( posix_openpt) . 0 errno . : if (posix_fadvise(...) < 0) { . : if (posix_fadvise(...) > 0) { bugprone-random-generator-seed (engine adaptor) srand() (constant expression) (seed) . . : 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 } DisallowedSeedTypes . time_t,std::time_t . CERT C++ : MSC51-CPP. Ensure your random number generator is properly seeded MSC32-C. Properly seed pseudorandom number generators . bugprone-raw-memory-call-on-non-trivial-type C memset memcpy memcmp (non-trivial types) . : memset std::memset std::memcpy memcpy std::memmove memmove std::strcpy strcpy memccpy stpncpy strncpy std::memcmp memcmp std::strcmp strcmp strncmp. MemSetNames memset . (semicolon) . . MemCpyNames memcpy . . . MemCmpNames memcmp . . . CERT C++ : OOP57-CPP. Prefer special member functions and overloaded operators to C Standard Library functions . bugprone-redundant-branch-condition if if . : bool onFire = isBurning(); if (onFire) { if (onFire) scream(); } onFire if if . onFire . <<>> (&&) <<>> (||) : bool onFire = isBurning(); if (onFire) { if (onFire && peopleInTheBuilding > 0) scream(); } bool onFire = isBurning(); if (onFire) { if (onFire || isCollapsing()) scream(); } (<<>> ) && . (<<>> ) if . if <<>> (&&) : bool onFire = isBurning(); if (onFire && fireFighters < 10) { if (someOtherCondition()) { if (onFire) scream(); } } ( <<>> (&&) <<>> (&&) <<>> (||)). if . : bool onFire = isBurning(); if (onFire) { tryToExtinguish(onFire); if (onFire && peopleInTheBuilding > 0) scream(); } volatile ( ) . else : bool onFire = isBurning(); if (onFire) { scream(); } else { if (!onFire) { continueWork(); } } . : if (peopleInTheBuilding == 1) { if (peopleInTheBuilding == 1) { doSomething(); } } bugprone-reserved-identifier cert-dcl37-c cert-dcl51-cpp . (implementation) . C C++ : o (underscore) o (global namespace) . C C++ . (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 . . () 'zombie names' C++ C . DCL37-C CERT C Do not declare or define a reserved identifier C++ DCL51-CPP Do not declare or define a reserved identifier . Invert true . false . AllowedIdentifiers (regular expressions) . . bugprone-return-const-ref-from-parameter return (constant reference) . xvalue (use-after-free) . C++ xvalue . . struct S { int v; S(int); ~S(); }; const S &fn(const S &a) { return a; } const S& s = fn(S{1}); s.v; // use after free (overload) const & && . use-after-free . && deleted . const & const & && . [[clang::lifetimebound]] . Clang -Wdangling . lifetimebound . const int &f(const int &a [[clang::lifetimebound]]) { return a; } // no warning const int &v = f(1); // warning: temporary bound to local reference 'v' will be destroyed at the end of the full-expression [-Wdangling] bugprone-shared-ptr-array-mismatch C++ ( shared pointer) . std::shared_ptr new T[] . delete delete[] . std::shared_ptr delete . ( ) shared_ptr shared_ptr . : std::shared_ptr x(new Foo[10]); // -> std::shared_ptr x(new Foo[10]); // ^ warning: shared pointer to non-array is initialized with array [bugprone-shared-ptr-array-mismatch] std::shared_ptr 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 x3(new Foo[10], [](const Foo *ptr) { delete[] ptr; }); // no warning struct S { std::shared_ptr x(new Foo[10]); // no replacement in this case // ^ warning: shared pointer to non-array is initialized with array [bugprone-shared-ptr-array-mismatch] }; MEM51-CPP CERT C++ Properly deallocate dynamically allocated resources . std::shared_ptr . bugprone-signal-handler (signal handler) . C++ . C: o (non-asynchronous-safe) . C++14: o . o C++ . C C++ . o C ( ) . C++17 . (Asynchronous-safety) . (system header) . () . . . SIG30-C CERT C Call only asynchronous-safe functions within signal handlers MSC54-CPP A signal handler must be a plain old function . cert-sig30-c cert-msc54-cpp . AsyncSafeFunctionSet (asynchronous-safe) ( signal handler ) . : o minimal CERT SIG30-C abort() _Exit() quick_exit() signal() . o POSIX POSIX.1-2017 ( ). : _Exit _exit abort accept access aio_error aio_return aio_suspend alarm bind cfgetispeed cfgetospeed cfsetispeed cfsetospeed chdir chmod chown clock_gettime close connect 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 getsockname 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 setuid shutdown sigaction sigaddset sigdelset sigemptyset sigfillset sigismember siglongjmp signal sigpause sigpending sigprocmask sigqueue sigset sigsuspend sleep sockatmark socket socketpair stat stpcpy stpncpy strcat strchr strcmp strcpy strcspn strlen strncat strncmp strncpy strnlen strpbrk strrchr strspn strstr strtok_r symlink symlinkat tcdrain tcflow tcflush tcgetattr tcgetpgrp tcsendbreak tcsetattr tcsetpgrp time timer_getoverrun timer_gettime timer_settime times umask uname unlink unlinkat utime utimensat utimes wait waitpid wcpcpy wcpncpy wcscat wcschr wcscmp wcscpy wcscspn wcslen wcsncat wcsncmp wcsncpy wcsnlen wcspbrk wcsrchr wcsspn wcsstr wcstok wmemchr wmemcmp wmemcpy wmemmove wmemset write quick_exit POSIX . POSIX . bugprone-signed-char-misuse cert-str34-c (alias) . CERT DiagnoseSignedUnsignedCharComparisons false . signed char -> integer . signed char ASCII . (explicit) (implicit) . signed char -> integer ( [0..255]) [-128..127] . signed char unsigned char [0..255] . char . . signed char unsigned char C++ . . signed char ASCII [-128..-1] unsigned char [128..255] . char signed char . -funsigned-char -fsigned-char . : o signed char (integer) o signed char unsigned char / o signed char : STR34-C. Cast characters to unsigned char before converting to larger integer sizes CERT char ASCII . -1 EOF 255 (two's complement) char -1 . . 255 . #define EOF (-1) int read(void) { char CChar; int IChar = EOF; if (readChar(CChar)) { IChar = CChar; } return IChar; } char unsigned char . #define EOF (-1) int read(void) { char CChar; int IChar = EOF; if (readChar(CChar)) { IChar = static_cast(CChar); } return IChar; } char (signedness) . ASCII signed char unsigned char false . bool compare(signed char SChar, unsigned char USChar) { if (SChar == USChar) return true; return false; } (cast) . bool compare(signed char SChar, unsigned char USChar) { if (static_cast(SChar) == USChar) return true; return false; } CharTypedefsToIgnore typedef - (semicolon) . typedef char signed char . typedef sal_Int8 int8_t . . . DiagnoseSignedUnsignedCharComparisons true signed char unsigned char . true . bugprone-sizeof-container sizeof STL . .size() . class/struct std:: const size() std::bitset std::array. : 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 std_array; int d = sizeof(std_array); // no warning, probably intended. bugprone-sizeof-expression sizeof . sizeof ( ) . . 'sizeof(K)' sizeof . ( int) . . #define BUFLEN 42 char buf[BUFLEN]; memset(buf, 0, sizeof(BUFLEN)); // sizeof(42) ==> sizeof(int) 'sizeof(expr)' enum sizeof enum sizeof . : 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()); ... } 'sizeof(this)' this . sizeof(this) . . class Point { [...] size_t size() { return sizeof(this); } // should probably be sizeof(*this) [...] }; 'sizeof(char*)' char* A = "" char A[] = "" . char[] char* . sizeof char* () . const char* kMessage = "Hello World!"; // const char kMessage[] = "..."; void getMessage(char* buf) { memcpy(buf, kMessage, sizeof(kMessage)); // sizeof(char*) } 'sizeof(A*)' . (explicit cast) (implicit conversion) . int A[10]; memset(A, 0, sizeof(A + 0)); struct Point point; memset(point, 0, sizeof(&point)); 'sizeof(...)/sizeof(...)' sizeof . . int . 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] } sizeof(Values) char* . '10' 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*] } 'sizeof' 'sizeof' sizeof . / * . const char kMessage[] = "Hello World!"; void getMessage(char* buf) { memcpy(buf, kMessage, sizeof(kMessage) * sizeof(char)); // sizeof(kMessage) / sizeof(char) } arraysize . sizeof . extern Object objects[100]; void InitializeObjects() { memset(objects, 0, arraysize(objects) * sizeof(Object)); // sizeof(objects) } 'sizeof(sizeof(...))' sizeof sizeof . #define INT_SZ sizeof(int) int buf[] = { 42 }; void getInt(int* dst) { memcpy(dst, buf, sizeof(INT_SZ)); // sizeof(sizeof(int)) is suspicious. } 'sizeof(...)' . sizeof . ( ptrdiff_t) " " . " " sizeof P1 - P2 == N * sizeof(T) ( P1 - P2 == N) (P1 - P2) / sizeof(T) P1 - P2. void splitFour(const Obj* Objs, size_t N, Obj Delimiter) { const Obj *P = Objs; while (P < Objs + N) { if (*P == Delimiter) { break; } } if (P - Objs != 4 * sizeof(Obj)) { // Expecting a distance multiplied by sizeof is suspicious. error(); } } void iterateIfEvenLength(int *Begin, int *End) { auto N = (Begin - End) / sizeof(int); // Dividing by sizeof() is suspicious. if (N % 2) return; // ... } Ptr + N N " " " ". sizeof (out of bounds) . Ptr + sizeof(T) sizeof(T) . sizeof sizeof . () sizeof () __ sizeof . WarnOnOffsetDividedBySizeOf . alignof offsetof "" . struct Message { /* ... */; char Flags[8]; }; void clearFlags(Message *Array, size_t N) { const Message *End = Array + N; while (Array < End) { memset(Array + offsetof(Message, Flags), // Suspicious pointer arithmetic using offsetof()! 0, sizeof(Message::Flags)); ++Array; } } cert-arr39-c . CERT C : ARR39-C. Do not add or subtract a scaled integer to a pointer . (pointee) 1 ( char) . WarnOnSizeOfConstant true sizeof(CONSTANT) . true . WarnOnSizeOfIntegerExpression true sizeof(expr) . false . WarnOnSizeOfThis true sizeof(this) . true . WarnOnSizeOfCompareToConstant true sizeof(expr) <= k k k 0 0x8000 . true . WarnOnSizeOfPointerToAggregate true sizeof (pointer-to-aggregate) ( array + 2 (int *)array) . true . WarnOnSizeOfPointer true sizeof ( ). CWE 467 . false . WarnOnOffsetDividedBySizeOf true (pointer arithmetic) sizeof(...) Ptr + Bytes / sizeof(*T). true . WarnOnSizeOfInLoopTermination true sizeof . sizeof / long arr[10]; for(int i = 0; i < sizeof(arr); i++) { ... }. true . bugprone-spuriously-wake-up-functions cnd_wait cnd_timedwait wait wait_for wait_until . if (condition_predicate) { condition.wait(lk); } if (condition_predicate) { if (thrd_success != cnd_wait(&condition, &lock)) { } } CERT C++ CON54-CPP. Wrap functions that can spuriously wake up in a loop CERT C CON36-C. Wrap functions that can spuriously wake up in a loop . bugprone-standalone-empty empty() (range) . clear() . empty() . clear() . empty clear() . : std::vector v; ... v.empty(); clear() : std::vector v; ... v.clear(); o empty() (class template definition) ( ) . [[nodiscard]] . bugprone-std-namespace-modification std posix (undefined behavior) . std ( posix) ( ) ( ) . ( ) std posix : o (template specialization) . o . o . o . o . : namespace std { int x; // warning: modification of 'std' namespace can result in undefined behavior [bugprone-dont-modify-std-namespace] } namespace posix::a { // warning: modification of 'posix' namespace can result in undefined behavior } template <> struct ::std::hash { // 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 { // no warning: specialization with user-defined type unsigned long operator()(const MyData &K) const { return K.data; } }; namespace std { template <> void swap(bool &a, bool &b); // warning: modification of 'std' namespace can result in undefined behavior template <> bool less::operator()(MyData &&, MyData &&) const { // warning: modification of 'std' namespace can result in undefined behavior return true; } } CERT C++ DCL58-CPP. Do not modify the standard namespaces . bugprone-string-constructor (constructors) . ('fill') . : std::string str('x', 50); // should be str(50, 'x') . : std::string("test", 200); // Will include random characters after "test". std::string("test", 2, 5); // Will include random characters after "st". std::string_view("test", 200); . . : std::string("test", 0); // Creation of an empty string. std::string("test", 1, 0); std::string_view("test", 0); std::out_of_range . : std::string("test", -1, 10); // Negative first character position. std::string("test", 10, 10); // First character position is bigger than string literal character range". WarnOnLargeLength true LargeLengthThreshold . true . LargeLengthThreshold . 0x800000 . StringNames ::std::basic_string;::std::basic_string_view . - (semicolon) . ::std::basic_string std::string std::wstring . ::std::basic_string;llvm::StringRef;QString . bugprone-string-integer-assignment std::basic_string (std::string std::wstring ) . std::basic_string : basic_string& operator=( CharT ch ); (cast) . std::string s; int x = 5965; s = 6; s = x; . std::string s; int x = 5965; s = '6'; s = std::to_string(x); (false positives) (explicit cast) . std::string s; s = static_cast(6); bugprone-string-literal-with-embedded-nul NUL . (hexadecimal) \x42 (escape ). \0x42 \0 NUL . const char* Example[] = "Invalid character: \0x12 should be \x12"; const char* Bytes[] = "\x03\0x02\0x01\0x00\0xFF\0xFF\0xFF"; Truncated literal (string-like) NUL . char* ( NUL) . NUL NUL . NUL () . 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 null const CharT* std::basic_string_view . (braced initializer list) .empty() . (undefined behavior) . const CharT* null . (overload) : wg21.link/p2166 NULL ( __null ) 0 modernize-use-nullptr 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 ... 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 : "A" (const CharT*) (value-initializes) (null dereference) . nullptr ClangTidy . : "B" (const CharT*, size_type) 0 . ClangTidy . bugprone-suspicious-enum-usage enum ( ) . 1. "ADD" "bitwise OR" enum (disjoint) . StrictMode <#cmdoption-arg-StrictMode> . enum () : o enum ( ) o enum ( "bitwise OR" enum) o / enum + "bitwise OR" . 2. += |=. 3. | + enum enum . 4. | + enum enum . : 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. StrictMode : 0. enum (bitmask) . bugprone-suspicious-include include (implementation file) ODR . : #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 // Warning, filename is suspicious. IgnoredRegex (regular expression) . . bugprone-suspicious-memory-comparison memcmp() . : : (Non-standard-layout type) (object representation) (value representation) . : . (padding) (floating-point) . : EXP42-C. Do not compare padding data FLP37-C. Do not use object representations to compare floating-point values CERT C++ : OOP57-CPP. Prefer special member functions and overloaded operators to C Standard Library functions EXP62-CPP. Do not access the bits of an object representation that are not part of the object's value representation cert-exp42-c . bugprone-suspicious-memset-usage memset() . void* memset(void* destination, int fill_value, size_t byte_count) : : ``'0'`` . '0' 0 . memset '0' . : (truncated) memset fill_value unsigned char . fill_value unsigned character . : memset byte_count fill_value . . cpplint.py : runtime/memset. : 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 ( ) (concatenate) . . : const char* A[] = "This is a test"; const char* B[] = "This" " is a " "test"; (array initializer list) . const char* Test[] = { "line 1", "line 2" // Missing comma! "line 3", "line 4", "line 5" }; "line 2line3" ( Test[1]) . Clang . : const char* SupportedFormat[] = { "Error %s", "Code " PRIu64, // May warn here. "Warning %s", }; SizeThreshold . 5U . RatioThreshold [0, 1.0] . ".2" . MaxConcatenatedTokens . 5U . bugprone-suspicious-realloc-usage realloc : p = realloc(p, size); realloc (null) . . p = realloc(p, size); q = realloc(p, size); . ( realloc) (unresolved types) . realloc realloc . q = p void *q = p p = realloc(p, ...) . realloc ( ) . p . : 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 . if while for for-range ( ) . if (x < y); { x++; } if x . while ((line = readLine(file)) != NULL); processLine(line); processLine() while line == NULL . . if (x >= y); x -= y; if ( ). . . : while (readWhitespace()); Token t = readNextToken(); while - . : while (readWhitespace()); Token t = readNextToken(); ... : while (readWhitespace()) ; Token t = readNextToken(); . bugprone-suspicious-string-compare . C C++ . . if (strcmp(...)) // if (!strcmp(...)) // if (strcmp(...) != 0) // ( strcmp) . : < 0 > 0 == 0 . 1 -1 . if (strcmp(...) == -1) // . (cast) . (context) . if (strcmp(...) < 0.) // . WarnOnImplicitComparison true . true . WarnOnLogicalNotComparison true (logical not) . false . StringCompareLikeFunctions . . : __builtin_memcmp __builtin_strcasecmp __builtin_strcmp __builtin_strncasecmp __builtin_strncmp _mbscmp _mbscmp_l _mbsicmp _mbsicmp_l _mbsnbcmp _mbsnbcmp_l _mbsnbicmp _mbsnbicmp_l _mbsncmp _mbsncmp_l _mbsnicmp _mbsnicmp_l _memicmp _memicmp_l _stricmp _stricmp_l _strnicmp _strnicmp_l _wcsicmp _wcsicmp_l _wcsnicmp _wcsnicmp_l lstrcmp lstrcmpi memcmp memicmp strcasecmp strcmp strcmpi stricmp strncasecmp strncmp strnicmp wcscasecmp wcscmp wcsicmp wcsncmp wcsnicmp wmemcmp. bugprone-suspicious-stringview-data-usage std::string_view::data() null . data() size() length() . data() null . c_str() std::string_view data() API C null . data() null API null . std::string_view std::string . std::string string-view explicit std::string_view std::string . .data() . : void printString(const std::string& str) { std::cout << "String: " << str << std::endl; } void something(std::string_view sv) { printString(sv.data()); } sv printString (explicit) std::string . sv.data() . StringViewTypes string view . (regular expressions) . : ::std::basic_string_view;::llvm::StringRef. AllowedCallees .data() . . . : . bugprone-swapped-arguments . . . void printNumbers(int a, float b); int main() { // : float int int float printNumbers(10.0f, 5); return 0; } : - (user-defined) - - - - ( ) . . . (implicit casts) . . . . (false positives) . bugprone-switch-missing-default-case switch default enum . switch default . switch default switch . switch default . default . : // 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; } : enum switch enum ( -Wswitch) . enum . : CppCoreGuideline ES.79 switch default . bugprone-tagged-union-member-count tagged union (tags) union . struct class tagged union union enum union enum. union enum std . : enum Tags { Tag1, Tag2, }; struct TaggedUnion { // warning: tagged union has more data members (3) than tags (2) enum Tags Kind; union { int I; float F; char *Str; } Data; }; union enum std . #include struct NotTaggedUnion { enum MyEnum { MyEnumConstant1, MyEnumConstant2 } En; pthread_mutex_t Mutex; }; pthread_mutex_t typedef union tagged union enum union . (false-positive) union enum std union enum tagged union . enum enum union . enum enum " " enum . : enum TagWithLast { Tag1 = 0, Tag2 = 1, Tag3 = 2, LastTag = 2 }; enum TagWithCounter { Tag1, // is 0 Tag2, // is 1 Tag3, // is 2 TagCount, // is 3 }; enum enum . enum (alias) enum . enum ( TagCount ) enum enum CountingEnumPrefixes CountingEnumSuffixes enum . (heuristic) enum . (EnableCountingEnumHeuristic) (CountingEnumPrefixes CountingEnumSuffixes). CountingEnumPrefixes CountingEnumSuffixes . : // Enum count is 3, because the value 2 is counted only once enum TagWithLast { Tag1 = 0, Tag2 = 1, Tag3 = 2, LastTag = 2 }; // Enum count is 3, because TagCount is heuristically excluded enum TagWithCounter { Tag1, // is 0 Tag2, // is 1 Tag3, // is 2 TagCount, // is 3 }; EnableCountingEnumHeuristic enum (counting enum heuristic) . CountingEnumPrefixes CountingEnumSuffixes enum . . EnableCountingEnumHeuristic false : enum TagWithCounter { Tag1, Tag2, Tag3, TagCount, }; struct TaggedUnion { TagWithCounter Kind; union { int A; long B; char *Str; float F; } Data; }; EnableCountingEnumHeuristic true : enum TagWithCounter { Tag1, Tag2, Tag3, TagCount, }; struct TaggedUnion { // warning: tagged union has more data members (4) than tags (3) TagWithCounter Kind; union { int A; long B; char *Str; float F; } Data; }; CountingEnumPrefixes CountingEnumSuffixes . CountingEnumSuffixes CountingEnumPrefixes CountingEnumSuffixes - (semicolon) enum . (case insensitively) enum . EnableCountingEnumHeuristic false . CountingEnumSuffixes count CountingEnumPrefixes . EnableCountingEnumHeuristic true CountingEnumSuffixes count;size : enum TagWithCounterCount { Tag1, Tag2, Tag3, TagCount, }; struct TaggedUnionCount { // warning: tagged union has more data members (4) than tags (3) TagWithCounterCount Kind; union { int A; long B; char *Str; float F; } Data; }; enum TagWithCounterSize { Tag11, Tag22, Tag33, TagSize, }; struct TaggedUnionSize { // warning: tagged union has more data members (4) than tags (3) TagWithCounterSize Kind; union { int A; long B; char *Str; float F; } Data; }; EnableCountingEnumHeuristic true CountingEnumPrefixes maxsize;last_ : enum TagWithCounterLast { Tag1, Tag2, Tag3, last_tag, }; struct TaggedUnionLast { // warning: tagged union has more data members (4) than tags (3) TagWithCounterLast tag; union { int I; short S; char *C; float F; } Data; }; enum TagWithCounterMaxSize { Tag1, Tag2, Tag3, MaxSizeTag, }; struct TaggedUnionMaxSize { // warning: tagged union has more data members (4) than tags (3) TagWithCounterMaxSize tag; union { int I; short S; char *C; float F; } Data; }; StrictMode (tags) union . . StrictMode <#cmdoption-arg-StrictMode> false : struct TaggedUnion { enum { Tag1, Tag2, Tag3, } Tags; union { int I; float F; } Data; }; StrictMode <#cmdoption-arg-StrictMode> true : struct TaggedUnion { // warning: tagged union has fewer data members (2) than tags (3) enum { Tag1, Tag2, Tag3, } Tags; union { int I; float F; } Data; }; do while (false) continue continue . void f() { do { // some code continue; // terminating continue // some other code } while(false); bugprone-throw-keyword-missing throw . ( ) 'EXCEPTION' 'Exception' 'exception' (throw) . : void f(int i) { if (i < 0) { // Exception is created but is not thrown. std::runtime_error("Unexpected argument"); } } bugprone-throwing-static-initialization static thread_local . References ERR58-CPP CERT C++ . ()main . bugprone-too-small-loop-variable for << >> ("too small") . int main() { long size = 294967296l; for (short i = 0; i < size; ++i) {} } for short [0..size] . size (container) . int doSomething(const std::vector& items) { for (short i = 0; i < items.size(); ++i) {} } ( ) . -Wtautological-constant-out-of-range-compare . Options MagnitudeBitsUpperLimit (magnitude bits) . . . 31 () unsigned int int ( signed int ). 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 : (flow-sensitive) . clang-tidy (RAM CPU) . std::optional absl::optional base::Optional folly::Optional bsl::optional BloombergLP::bdlb::NullableValue . optional . optional value operator* operator-> . (undefined behavior) . . optional ( ) optional . optional::has_value optional ( std::make_optional std::optional ). optional . Unsafe access patterns Access the value without checking if it exists : void f(std::optional opt) { use(*opt); // unsafe: it is unclear whether `opt` has a value. } optional . : void f(std::optional opt) { if (opt.has_value()) { } else { use(opt.value()); // unsafe: it is clear that `opt` does *not* have a value. } } . . : void f(Foo foo) { if (foo.take().has_value()) { use(*foo.take()); // unsafe: it is unclear whether `foo.take()` has a value. } } : (accessor) accessor (heuristic) . const API ( const * const ) . -- ( ) . const . API (invariants) API . : void f(Foo foo) { if (foo.HasProperty("bar")) { use(*foo.GetProperty("bar")); // unsafe: it is unclear whether `foo.GetProperty("bar")` has a value. } } optional . . optional . : void g(std::optional opt) { use(*opt); // unsafe: it is unclear whether `opt` has a value. } void f(std::optional opt) { if (opt.has_value()) { g(opt); } } optional . : void f(std::optional opt) { if (opt.has_value()) { use(*opt); } } (semantic) (syntactic). optional . : void f(std::optional opt1) { if (opt1.has_value()) { std::optional opt2 = opt1; use(*opt2); } } CHECK DCHECK . optional . : void f(std::optional opt) { DCHECK(opt.has_value()); use(*opt); } optional . : void f(std::optional opt) { bool safe = false; if (opt.has_value() && SomeOtherCondition()) { safe = true; } // ... more code... if (safe) { use(*opt); } } (accessor) const. ( const ) . : void f(Foo foo) { if (const auto& foo_opt = foo.take(); foo_opt.has_value()) { use(*foo_opt); } } API API optional -- optional . : void f(Foo foo) { if (const auto& property = foo.GetProperty("bar")) { use(*property); } } HasProperty GetProperty . optional optional . : void g(int val) { use(val); } void f(std::optional opt) { if (opt.has_value()) { g(*opt); } } struct S { std::optional 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); } } using optional using . : using OptionalInt = std::optional; void f(OptionalInt opt) { use(opt.value()); // unsafe: it is unclear whether `opt` has a value. } optional . . optional . operator*() value() value() ( ) operator*() (UB) optional value() CHECK() operator*() value() ( ) value() operator*() . operator*() : o . . . o . . -- . IgnoreSmartPointerDereference true optional (operator* operator->) optional . . operator[] . false . IgnoreValueCalls true optional::value() . operator*() operator->() . value() UB . false . bugprone-unchecked-string-to-number-conversion atoi() scanf() . strtol() . #include 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 */ } } CERT C : ERR34-C. Detect errors when converting a string to a number . bugprone-undefined-memory-manipulation memset() memcpy() memmove() TriviallyCopyable (undefined behavior) . TriviallyCopyable C++ . . . . memcpy std::string (double free) . #include #include 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 . (delegating constructor) . bugprone-unhandled-exception-at-new new std::bad_alloc . new std::bad_alloc . (nonthrowing) new . new . nonthrowing (propagate) . std::bad_alloc std::exception (catch-all) . operator new noexcept std::bad_alloc ( ) . . 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 . CERT WarnOnlyIfThisHasSuspiciousField false . copy-and-swap copy-and-move . (false positives) C . C . : OOP54-CPP. Gracefully handle self-copy assignment . : 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; } }; C++ . (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; } }; copy-and-swap ( ) this (swap) : 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; } }; . copy-and-move ( ) this (move) ( ): 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; } }; Options WarnOnlyIfThisHasSuspiciousField true (copy assignment operator) ( C ++C) . true . bugprone-unintended-char-ostream-output unsigned char signed char ostream . unsigned char (uint8_t) signed char (int8_t) . operator<< std::ostream . . uint8_t v = 65; std::cout << v; // output 'A' instead of '65' (cast) unsigned char unsigned int signed char int . std::cout << static_cast(v); // when v is unsigned char std::cout << static_cast(v); // when v is signed char + int (type promotion). std::cout << +v; char . std::cout << static_cast(v); Options AllowedTypes - (semicolon) char : . (type aliases) unsigned char uint8_t typedef unsigned char . unsigned char;signed char . CastTypeName CastTypeName (fix-it) CastTypeName . fix-it . bugprone-unique-ptr-array-mismatch ++C ( std::unique_ptr) . std::unique_ptr new new T[] . delete delete[] . std::unique_ptr delete . unique_ptr deleter . ( ) unique_ptr unique_ptr . : std::unique_ptr x(new Foo[10]); // -> std::unique_ptr x(new Foo[10]); // ^ warning: unique pointer to non-array is initialized with array std::unique_ptr x1(new Foo), x2(new Foo[10]); // no replacement // ^ warning: unique pointer to non-array is initialized with array D d; std::unique_ptr x3(new Foo[10], d); // no warning (custom deleter used) struct S { std::unique_ptr x(new Foo[10]); // no replacement in this case // ^ warning: unique pointer to non-array is initialized with array }; MEM51-CPP CERT C++ Coding Standard : Properly deallocate dynamically allocated resources std::unique_ptr . bugprone-unsafe-functions (deprecated) . Annex K. <> C11 . CERT C Coding Standard : o MSC24-C: . o MSC33-C: asctime() . cert-msc24-c cert-msc33-c . Unsafe functions ReportDefaultFunctions . Annex K. Annex K. : asctime, asctime_r, bsearch, ctime, fopen, fprintf, freopen, fscanf, fwprintf, fwscanf, getenv, gets, gmtime, localtime, mbsrtowcs, mbstowcs, 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, vwprintf, vwscanf, wcrtomb, wcscat, wcscpy, wcslen, wcsncat, wcsncpy, wcsrtombs, wcstok, wcstombs, wctomb, wmemcpy, wmemmove, wprintf, wscanf. Annex K. : o asctime, asctime_r : strftime o gets : fgets Annex K : o rewind : fseek o setbuf : setvbuf ReportMoreUnsafeFunctions : o bcmp : memcmp o bcopy : memcpy_s Annex K memcpy o bzero : memset_s Annex K memset o getpw : getpwuid o vfork : posix_spawn CERT : atof, atoi, atol, atoll, tmpfile. Annex K : o __STDC_LIB_EXT1__: (feature macro) Annex K. "Bounds-checking interfaces" o __STDC_WANT_LIB_EXT1__: Annex K. . Annex K. . __STDC_LIB_EXT1__ __STDC_WANT_LIB_EXT1__ 1 . CustomFunctions . (newline) : bugprone-unsafe-functions.CustomFunctions=" functionRegex1[, replacement1[, reason1]]; functionRegex2[, replacement2[, reason2]]; ... " POSIX . (: (?!) .) reason . is marked as unsafe. replacement it should not be used . reason > . replacement . ( > .) original . . // bugprone-unsafe-functions.CustomFunctions: // ^original$, replacement, is deprecated; // Using the fully custom message syntax: // ^suspicious$,,> should be avoided if possible. original(); // warning: function 'original' is deprecated; 'replacement' should be used instead. suspicious(); // warning: function 'suspicious' should be avoided if possible. ::std::original(); // no-warning original_function(); // no-warning : ( std::original) (original) . :: ( ^::) (::std::original) . : // bugprone-unsafe-functions.CustomFunctions: // ^memcpy$,,>is recommended to have compiler hardening using '_FORTIFY_SOURCE'; // ^printf$,,>is recommended to have the '-Werror=format-security' compiler warning flag; memcpy(dest, src, 999'999); // warning: function 'memcpy' is recommended to have compiler hardening using '_FORTIFY_SOURCE' printf(raw_str); // warning: function 'printf' is recommended to have the '-Werror=format-security' compiler warning flag : C++ (template) C++ . (Type aliases) . open std::ifstream ::std::basic_ifstream::open . ::std::basic_ifstream<[^>]*>::open . ReportMoreUnsafeFunctions true API ( POSIX) . . true . ReportDefaultFunctions true . Custom functions false . true . CustomFunctions (;) . . . #ifndef __STDC_LIB_EXT1__ #error "Annex K is not supported by the current standard library implementation." #endif #define __STDC_WANT_LIB_EXT1__ 1 #include // Defines functions from Annex K. #include 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 (non-trivial) . : o (trivial) (trivially copyable) o (references) (pointers) o catch o static thread local o (structured bindings) o [[maybe_unused]] o (name-independent) IncludeTypes .* ExcludeTypes . my_lock . std::mutex my_lock; // my_lock local variable is never used future2 . std::future future1; std::future future2; // ... MyObject foo = future1.get(); // future2 is not used. IncludeTypes - . : o ::std::.*mutex o ::std::future o ::std::basic_string o ::std::basic_regex o ::std::basic_istringstream o ::std::basic_stringstream o ::std::bitset o ::std::filesystem::path ExcludeTypes - IncludeTypes . . bugprone-unused-raii RAII . (scoped lock) . { scoped_lock(&global_mutex); critical_section(); } (destructor) scoped_lock critical_section . (heuristics) : o . . o (trivial destructors) . RAII . o (compound statement) ( ). o . bugprone-unused-return-value . . (operator overloading) . CheckedFunctions - . (regexp) . (scope) . : ^::std::async$, ^::std::launder$, ^::std::remove$, ^::std::remove_if$, ^::std::unique$, ^::std::unique_ptr::release$, ^::std::basic_string::empty$, ^::std::vector::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::setprecision$, ^::std::setw$, ^::std::upper_bound$, ^::std::vector::at$, ^::bsearch$, ^::ferror$, ^::feof$, ^::isalnum$, ^::isalpha$, ^::isblank$, ^::iscntrl$, ^::isdigit$, ^::isgraph$, ^::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$, ^::strcasecmp$, ^::strsignal$, ^::ttyname$ o std::async(). (synchronous) . o std::launder(). . << >> (laundered) . o std::remove() std::remove_if() std::unique(). (iterator) . . o std::unique_ptr::release(). (resource leaks) . release() reset() . o std::basic_string::empty() std::vector::empty(). clear() . CheckedReturnTypes - . : ^::std::error_code$, ^::std::error_condition$, ^::std::errc$, ^::std::expected$, ^::boost::system::error_code$ AllowCastToVoid (cast) void . : false. cert-err33-c <> (alias) . bugprone-use-after-move (move) : std::string str = "Hello, world!\n"; std::vector messages; messages.emplace_back(std::move(str)); std::cout << str; str . (reinitialize) . : messages.emplace_back(std::move(str)); str = "Greetings, stranger!\n"; std::cout << str; . (control flow) . . : if (condition) { messages.emplace_back(std::move(str)); } else { std::cout << str; } : for (int i = 0; i < 10; ++i) { std::cout << str; messages.emplace_back(std::move(str)); } ( .) (mutually exclusive) . ( i int ): if (i == 1) { messages.emplace_back(std::move(str)); } if (i == 2) { std::cout << str; } . (flow-sensitive but not path-sensitive) . : if (i == 1) { messages.emplace_back(std::move(str)); str = ""; } if (i == 2) { std::cout << str; } (dummy) : template void IS_INITIALIZED(T&) {} : if (i == 1) { messages.emplace_back(std::move(str)); } if (i == 2) { IS_INITIALIZED(str); std::cout << str; } - (non-const) ( ). (Unsequenced) C++ . : void f(int i, std::vector v); std::vector v = { 1, 2, 3 }; f(v[1], std::move(v)); (unsequenced) . . . (Move) std::move . (global) . std::move std::move rvalue . (move constructor) (move assignment operator) use-after-move . . (move semantics) std::move . std::move use-after-move . std::move rvalue . : std::vector 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)); . . : std::move try_emplace . bool try_emplace . ( Unsequenced moves, uses, and reinitializations ) std::move . perfect-forwarding std::forward use-after-move . void consume(int); void f(int&& i) { consume(std::forward(i)); consume(std::forward(i)); // use-after-move } (Use) ( ) . std::unique_ptr std::shared_ptr std::weak_ptr std::optional std::any . std::unique_ptr std::shared_ptr std::weak_ptr std::optional std::any reset . nullptr operator* operator-> operator[] nullptr . . (Reinitialization) : o . o non-const lvalue (non-const) . ( .) o clear() assign() basic_string vector deque forward_list list set map multiset multimap unordered_set unordered_map unordered_multiset unordered_multimap . o reset() std::unique_ptr std::shared_ptr std::weak_ptr std::optional std::any . o [[clang::reinitializes]] . struct -- struct . : 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; s s.str use-after-move . struct . S . struct use-after-move . (Options) InvalidationFunctions - (regular expressions) ( handle). (this) . . ReinitializationFunctions - . (*this) - . (static) . . bugprone-virtual-near-miss ( ) . : 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-arr39-c cert-arr39-c bugprone-sizeof-expression <> . cert-con36-c cert-con36-c bugprone-spuriously-wake-up-functions <> . cert-con54-cpp cert-con54-cpp bugprone-spuriously-wake-up-functions <> . cert-ctr56-cpp cert-ctr56-cpp bugprone-pointer-arithmetic-on-polymorphic-object <> . cert-dcl03-c cert-dcl03-c misc-static-assert <> . cert-dcl16-c cert-dcl16-c readability-uppercase-literal-suffix <> . cert-dcl37-c cert-dcl37-c bugprone-reserved-identifier <> . cert-dcl50-cpp cert-dcl50-cpp modernize-avoid-variadic-functions <> . DCL50-CPP CERT C++ : Do not define a C-style variadic function . cert-dcl51-cpp cert-dcl51-cpp bugprone-reserved-identifier <> . cert-dcl54-cpp cert-dcl54-cpp misc-new-delete-overloads <> . cert-dcl58-cpp cert-dcl58-cpp bugprone-std-namespace-modification <> . DCL58-CPP CERT C++ : Do not modify the standard namespaces . cert-dcl59-cpp cert-dcl59-cpp misc-anonymous-namespace-in-header <> . cert-env33-c cert-env33-c bugprone-command-processor <> . ENV33-C CERT C : Do not call system() . cert-err09-cpp cert-err09-cpp misc-throw-by-value-catch-by-reference <> . ERR09-CPP CERT C++ : Throw anonymous temporaries. CERT . cert-err33-c . . . : o aligned_alloc() o asctime_s() o at_quick_exit() o atexit() o bsearch() o bsearch_s() o btowc() o c16rtomb() o c32rtomb() o calloc() o clock() o cnd_broadcast() o cnd_init() o cnd_signal() o cnd_timedwait() o cnd_wait() o ctime_s() o fclose() o fflush() o fgetc() o fgetpos() o fgets() o fgetwc() o fopen() o fopen_s() o fprintf() o fprintf_s() o fputc() o fputs() o fputwc() o fputws() o fread() o freopen() o freopen_s() o fscanf() o fscanf_s() o fseek() o fsetpos() o ftell() o fwprintf() o fwprintf_s() o fwrite() o fwscanf() o fwscanf_s() o getc() o getchar() o getenv() o getenv_s() o gets_s() o getwc() o getwchar() o gmtime() o gmtime_s() o localtime() o localtime_s() o malloc() o mbrtoc16() o mbrtoc32() o mbsrtowcs() o mbsrtowcs_s() o mbstowcs() o mbstowcs_s() o memchr() o mktime() o mtx_init() o mtx_lock() o mtx_timedlock() o mtx_trylock() o mtx_unlock() o printf_s() o putc() o putwc() o raise() o realloc() o remove() o rename() o setlocale() o setvbuf() o scanf() o scanf_s() o signal() o snprintf() o snprintf_s() o sprintf() o sprintf_s() o sscanf() o sscanf_s() o strchr() o strerror_s() o strftime() o strpbrk() o strrchr() o strstr() o strtod() o strtof() o strtoimax() o strtok() o strtok_s() o strtol() o strtold() o strtoll() o strtoumax() o strtoul() o strtoull() o strxfrm() o swprintf() o swprintf_s() o swscanf() o swscanf_s() o thrd_create() o thrd_detach() o thrd_join() o thrd_sleep() o time() o timespec_get() o tmpfile() o tmpfile_s() o tmpnam() o tmpnam_s() o tss_create() o tss_get() o tss_set() o ungetc() o ungetwc() o vfprintf() o vfprintf_s() o vfscanf() o vfscanf_s() o vfwprintf() o vfwprintf_s() o vfwscanf() o vfwscanf_s() o vprintf_s() o vscanf() o vscanf_s() o vsnprintf() o vsnprintf_s() o vsprintf() o vsprintf_s() o vsscanf() o vsscanf_s() o vswprintf() o vswprintf_s() o vswscanf() o vswscanf_s() o vwprintf_s() o vwscanf() o vwscanf_s() o wcrtomb() o wcschr() o wcsftime() o wcspbrk() o wcsrchr() o wcsrtombs() o wcsrtombs_s() o wcsstr() o wcstod() o wcstof() o wcstoimax() o wcstok() o wcstok_s() o wcstol() o wcstold() o wcstoll() o wcstombs() o wcstombs_s() o wcstoumax() o wcstoul() o wcstoull() o wcsxfrm() o wctob() o wctrans() o wctype() o wmemchr() o wprintf_s() o wscanf() o wscanf_s() bugprone-unused-return-value <> . (cast) void AllowCastToVoid false . ERR33-C CERT C : << >> . : o NULL . : mblen mbrlen mbrtowc mbtowc wctomb wctomb_s cert-err34-c cert-err34-c bugprone-unchecked-string-to-number-conversion <> . cert-err52-cpp cert-err52-cpp modernize-avoid-setjmp-longjmp <> . ERR52-CPP CERT C++ : << setjmp() longjmp() >> . cert-err58-cpp cert-err58-cpp bugprone-throwing-static-initialization <> . ERR58-CPP CERT C++ : << main()>> . cert-err60-cpp cert-err60-cpp bugprone-exception-copy-constructor-throws <> . ERR60-CPP CERT C++ : << (nothrow) >> . cert-err61-cpp cert-err61-cpp misc-throw-by-value-catch-by-reference <> . cert-exp42-c cert-exp42-c bugprone-suspicious-memory-comparison <> . cert-fio38-c cert-fio38-c misc-non-copyable-objects <> . FIO38-C CERT C++ : << FILE >> . cert-flp30-c cert-flp30-c bugprone-float-loop-counter <> . FLP30-C CERT C : << >> . cert-flp37-c cert-flp37-c bugprone-suspicious-memory-comparison <> . cert-int09-c cert-int09-c readability-enum-initial-value <> . cert-mem57-cpp cert-mem57-cpp bugprone-default-operator-new-on-overaligned-type <> . MEM57-CPP CERT C++ : << operator new (over-aligned)>> . cert-msc24-c cert-msc24-c bugprone-unsafe-functions <> . cert-msc30-c cert-msc30-c misc-predictable-rand <> . MSC30-C CERT C : << rand() >> . cert-msc32-c cert-msc32-c bugprone-random-generator-seed <> . MSC32-C CERT C : << (seed) >> . cert-msc33-c cert-msc33-c bugprone-unsafe-functions <> . cert-msc50-cpp cert-msc50-cpp misc-predictable-rand <> . MSC50-CPP CERT C : << std::rand() >> . cert-msc51-cpp cert-msc51-cpp bugprone-random-generator-seed <> . MSC51-CPP CERT C++ : << (seed) >> . cert-msc54-cpp cert-msc54-cpp bugprone-signal-handler <> . cert-oop11-cpp cert-oop11-cpp performance-move-constructor-init <> . OOP11-CPP CERT C++ : << >> (Do not copy-initialize members or base classes from a move constructor). CERT . cert-oop54-cpp cert-oop54-cpp bugprone-unhandled-self-assignment <> . cert-oop57-cpp cert-oop57-cpp bugprone-raw-memory-call-on-non-trivial-type <> . OOP57-CPP CERT C++ : << C >> (Prefer special member functions and overloaded operators to C Standard Library functions) . cert-oop58-cpp cert-oop58-cpp bugprone-copy-constructor-mutates-argument <> . cert-pos44-c cert-pos44-c bugprone-bad-signal-to-kill-thread <> . cert-pos47-c cert-pos47-c concurrency-thread-canceltype-asynchronous <> . cert-sig30-c cert-sig30-c bugprone-signal-handler <> . cert-str34-c cert-str34-c bugprone-signed-char-misuse <> . clang-analyzer-core.BitwiseShift (bitwise shift) (undefined behaviour) . clang-analyzer-core.BitwiseShift Clang Static Analyzer Available Checkers . clang-analyzer-core.CallAndMessage Objective-C ( /null). clang-analyzer-core.CallAndMessage Clang Static Analyzer Available Checkers . clang-analyzer-core.DivideZero . clang-analyzer-core.DivideZero Clang Static Analyzer Available Checkers . clang-analyzer-core.NonNullParamChecker (null) 'nonnull' . clang-analyzer-core.NonNullParamChecker Clang Static Analyzer Available Checkers . clang-analyzer-core.NullDereference (dereference) (null) . clang-analyzer-core.NullDereference Clang Static Analyzer Available Checkers . clang-analyzer-core.StackAddressEscape (stack) (escape). clang-analyzer-core.StackAddressEscape Clang Static Analyzer Available Checkers . clang-analyzer-core.UndefinedBinaryOperatorResult . clang-analyzer-core.UndefinedBinaryOperatorResult Clang Static Analyzer Available Checkers . clang-analyzer-core.VLASize (VLA) . clang-analyzer-core.VLASize Clang Static Analyzer Available Checkers . clang-analyzer-core.uninitialized.ArraySubscript . clang-analyzer-core.uninitialized.ArraySubscript Clang Static Analyzer Available Checkers . clang-analyzer-core.uninitialized.Assign . clang-analyzer-core.uninitialized.Assign Clang Static Analyzer Available Checkers . clang-analyzer-core.uninitialized.Branch (branch conditions) . clang-analyzer-core.uninitialized.Branch Clang Static Analyzer Available Checkers . clang-analyzer-core.uninitialized.CapturedBlockVariable (capture) . clang-analyzer-core.uninitialized.CapturedBlockVariable Clang Static Analyzer Available Checkers . clang-analyzer-core.uninitialized.NewArraySize []new . clang-analyzer-core.uninitialized.NewArraySize Clang Static Analyzer Available Checkers . clang-analyzer-core.uninitialized.UndefReturn (caller) . clang-analyzer-core.uninitialized.UndefReturn Clang Static Analyzer Available Checkers . clang-analyzer-cplusplus.ArrayDelete (polymorphic) . clang-analyzer-cplusplus.ArrayDelete (alias) Clang Static Analyzer Available Checkers . clang-analyzer-cplusplus.InnerPointer ++C (re/deallocation) . clang-analyzer-cplusplus.InnerPointer (alias) Clang Static Analyzer Available Checkers . clang-analyzer-cplusplus.Move (use-after-move) ++C . clang-analyzer-cplusplus.Move (alias) Clang Static Analyzer Available Checkers . clang-analyzer-cplusplus.NewDelete (double-free) (use-after-free) . new/delete . clang-analyzer-cplusplus.NewDelete (alias) Clang Static Analyzer Available Checkers . clang-analyzer-cplusplus.NewDeleteLeaks (memory leaks) . new/delete . clang-analyzer-cplusplus.NewDeleteLeaks (alias) Clang Static Analyzer Available Checkers . clang-analyzer-cplusplus.PlacementNew placement new . clang-analyzer-cplusplus.PlacementNew (alias) Clang Static Analyzer Available Checkers . clang-analyzer-cplusplus.SelfAssignment ++C (self assignment) . clang-analyzer-cplusplus.SelfAssignment (alias) Clang Static Analyzer Available Checkers . clang-analyzer-cplusplus.StringChecker std::string ++C . clang-analyzer-cplusplus.StringChecker (alias) Clang Static Analyzer Available Checkers . clang-analyzer-deadcode.DeadStores . clang-analyzer-deadcode.DeadStores (alias) Clang Static Analyzer Available Checkers . clang-analyzer-fuchsia.HandleChecker Fuchsia . clang-analyzer-fuchsia.HandleChecker (alias) Clang Static Analyzer Available Checkers . clang-analyzer-nullability.NullPassedToNonnull null _Nonnull . clang-analyzer-nullability.NullPassedToNonnull (alias) Clang Static Analyzer Available Checkers . clang-analyzer-nullability.NullReturnedFromNonnull null _Nonnull . clang-analyzer-nullability.NullReturnedFromNonnull (alias) Clang Static Analyzer Available Checkers . clang-analyzer-nullability.NullableDereferenced nullable (dereference ) . clang-analyzer-nullability.NullableDereferenced (alias) Clang Static Analyzer Available Checkers . clang-analyzer-nullability.NullablePassedToNonnull nullable _Nonnull . clang-analyzer-nullability.NullablePassedToNonnull (alias) Clang Static Analyzer Available Checkers . clang-analyzer-nullability.NullableReturnedFromNonnull nullable _Nonnull . clang-analyzer-nullability.NullableReturnedFromNonnull (alias) Clang Static Analyzer Available Checkers . clang-analyzer-optin.core.EnumCastOutOfRange . clang-analyzer-optin.core.EnumCastOutOfRange (alias) Clang Static Analyzer Available Checkers . clang-analyzer-optin.cplusplus.UninitializedObject . clang-analyzer-optin.cplusplus.UninitializedObject (alias) Clang Static Analyzer Available Checkers . clang-analyzer-optin.cplusplus.VirtualCall / . clang-analyzer-optin.cplusplus.VirtualCall (alias) Clang Static Analyzer Available Checkers . clang-analyzer-optin.mpi.MPI-Checker MPI . clang-analyzer-optin.mpi.MPI-Checker (alias) Clang Static Analyzer Available Checkers . clang-analyzer-optin.osx.cocoa.localizability.EmptyLocalizationContextChecker NSLocalizedString (context) . clang-analyzer-optin.osx.cocoa.localizability.EmptyLocalizationContextChecker (alias) Clang Static Analyzer Available Checkers . clang-analyzer-optin.osx.cocoa.localizability.NonLocalizedStringChecker NSString NSString . clang-analyzer-optin.osx.cocoa.localizability.NonLocalizedStringChecker (alias) Clang Static Analyzer Available Checkers . clang-analyzer-optin.performance.GCDAntipattern (anti-patterns) Grand Central Dispatch. clang-analyzer-optin.performance.GCDAntipattern Clang Static Analyzer Available Checkers . clang-analyzer-optin.performance.Padding struct (padding) . clang-analyzer-optin.performance.Padding Clang Static Analyzer Available Checkers . clang-analyzer-optin.portability.UnixAPI (implementation-defined) UNIX/Posix. clang-analyzer-optin.portability.UnixAPI Clang Static Analyzer Available Checkers . clang-analyzer-optin.taint.TaintedAlloc ( ) . clang-analyzer-optin.taint.TaintedAlloc Clang Static Analyzer Available Checkers . clang-analyzer-osx.API Apple. clang-analyzer-osx.API Clang Static Analyzer Available Checkers . clang-analyzer-osx.NumberObjectConversion . clang-analyzer-osx.NumberObjectConversion Clang Static Analyzer Available Checkers . clang-analyzer-osx.ObjCProperty Objective-C. clang-analyzer-osx.ObjCProperty Clang Static Analyzer Available Checkers . clang-analyzer-osx.SecKeychainAPI API Secure Keychain. clang-analyzer-osx.SecKeychainAPI Clang Static Analyzer Available Checkers . clang-analyzer-osx.cocoa.AtSync nil mutex @synchronized . clang-analyzer-osx.cocoa.AtSync Clang Static Analyzer Available Checkers . clang-analyzer-osx.cocoa.AutoreleaseWrite (crash) autoreleasing pool Objective-C. clang-analyzer-osx.cocoa.AutoreleaseWrite Clang Static Analyzer Available Checkers . clang-analyzer-osx.cocoa.ClassRelease 'retain' 'release' 'autorelease' Class. clang-analyzer-osx.cocoa.ClassRelease Clang Static Analyzer Available Checkers . clang-analyzer-osx.cocoa.Dealloc Objective-C -dealloc . clang-analyzer-osx.cocoa.Dealloc Clang Static Analyzer Available Checkers . clang-analyzer-osx.cocoa.IncompatibleMethodTypes Objective-C (type incompatibilities). clang-analyzer-osx.cocoa.IncompatibleMethodTypes Clang Static Analyzer Available Checkers . clang-analyzer-osx.cocoa.Loops Cocoa. clang-analyzer-osx.cocoa.Loops Clang Static Analyzer Available Checkers . clang-analyzer-osx.cocoa.MissingSuperCall Objective-C super . clang-analyzer-osx.cocoa.MissingSuperCall Clang Static Analyzer Available Checkers . clang-analyzer-osx.cocoa.NSAutoreleasePool NSAutoreleasePool GC Objective-C. clang-analyzer-osx.cocoa.NSAutoreleasePool Clang Static Analyzer Available Checkers . clang-analyzer-osx.cocoa.NSError **NSError. clang-analyzer-osx.cocoa.NSError Clang Static Analyzer Available Checkers . clang-analyzer-osx.cocoa.NilArg nil ObjC. clang-analyzer-osx.cocoa.NilArg Clang Static Analyzer Available Checkers . clang-analyzer-osx.cocoa.NonNilReturnValue API nil . clang-analyzer-osx.cocoa.NonNilReturnValue Clang Static Analyzer Available Checkers . clang-analyzer-osx.cocoa.ObjCGenerics Objective-C. clang-analyzer-osx.cocoa.ObjCGenerics Clang Static Analyzer Available Checkers . clang-analyzer-osx.cocoa.RetainCount (reference count). clang-analyzer-osx.cocoa.RetainCount Clang Static Analyzer Available Checkers . clang-analyzer-osx.cocoa.RunLoopAutoreleaseLeak autorelease pool . clang-analyzer-osx.cocoa.RunLoopAutoreleaseLeak Clang Static Analyzer Available Checkers . clang-analyzer-osx.cocoa.SelfInit 'self' (initializer) . clang-analyzer-osx.cocoa.SelfInit (alias) Clang Static Analyzer Available Checkers . clang-analyzer-osx.cocoa.SuperDealloc '[super dealloc]' Objective-C . clang-analyzer-osx.cocoa.SuperDealloc (alias) Clang Static Analyzer Available Checkers . clang-analyzer-osx.cocoa.UnusedIvars ivar . clang-analyzer-osx.cocoa.UnusedIvars (alias) Clang Static Analyzer Available Checkers . clang-analyzer-osx.cocoa.VariadicMethodTypes Objective-C (variadic) Objective-C . clang-analyzer-osx.cocoa.VariadicMethodTypes (alias) Clang Static Analyzer Available Checkers . clang-analyzer-osx.coreFoundation.CFError *CFErrorRef . clang-analyzer-osx.coreFoundation.CFError (alias) Clang Static Analyzer Available Checkers . clang-analyzer-osx.coreFoundation.CFNumber API CFNumber . clang-analyzer-osx.coreFoundation.CFNumber (alias) Clang Static Analyzer Available Checkers . clang-analyzer-osx.coreFoundation.CFRetainRelease (null) CFRetain/CFRelease/CFMakeCollectable . clang-analyzer-osx.coreFoundation.CFRetainRelease (alias) Clang Static Analyzer Available Checkers . clang-analyzer-osx.coreFoundation.containers.OutOfBounds API 'CFArray' . clang-analyzer-osx.coreFoundation.containers.OutOfBounds (alias) Clang Static Analyzer Available Checkers . clang-analyzer-osx.coreFoundation.containers.PointerSizedValues 'CFArray' 'CFDictionary' 'CFSet' . clang-analyzer-osx.coreFoundation.containers.PointerSizedValues (alias) Clang Static Analyzer Available Checkers . clang-analyzer-security.FloatLoopCounter (CERT: FLP30-C, FLP30-CPP). clang-analyzer-security.FloatLoopCounter (alias) Clang Static Analyzer Available Checkers . clang-analyzer-security.PutenvStackArray putenv (/) . putenv . . clang-analyzer-security.PutenvStackArray (alias) Clang Static Analyzer Available Checkers . clang-analyzer-security.SetgidSetuidOrder setuid(getuid()) setgid(getgid()) ( ) . (seteuid setreuid setresuid GID ) . setuid(getuid()) ( GID) getuid() . clang-analyzer-security.SetgidSetuidOrder (alias) Clang Static Analyzer Available Checkers . clang-analyzer-security.cert.env.InvalidPtr . clang-analyzer-security.cert.env.InvalidPtr (alias) Clang Static Analyzer Available Checkers . clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling . clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling (alias) Clang Static Analyzer Available Checkers . clang-analyzer-security.insecureAPI.UncheckedReturn . clang-analyzer-security.insecureAPI.UncheckedReturn (alias) Clang Static Analyzer Available Checkers . clang-analyzer-security.insecureAPI.bcmp 'bcmp' . clang-analyzer-security.insecureAPI.bcmp (alias) Clang Static Analyzer Available Checkers . clang-analyzer-security.insecureAPI.bcopy 'bcopy' . clang-analyzer-security.insecureAPI.bcopy (alias) Clang Static Analyzer Available Checkers ..SS clang-analyzer-security.insecureAPI.bzero 'bzero' . clang-analyzer-security.insecureAPI.bzero (alias) Clang Static Analyzer Available Checkers . clang-analyzer-security.insecureAPI.decodeValueOfObjCType '-decodeValueOfObjCType:at:' . clang-analyzer-security.insecureAPI.decodeValueOfObjCType (alias) Clang Static Analyzer security.insecureAPI.decodeValueOfObjCType . clang-analyzer-security.insecureAPI.getpw 'getpw' . clang-analyzer-security.insecureAPI.getpw (alias) Clang Static Analyzer Available Checkers . clang-analyzer-security.insecureAPI.gets 'gets' . clang-analyzer-security.insecureAPI.gets (alias) Clang Static Analyzer Available Checkers . clang-analyzer-security.insecureAPI.mkstemp X 'mkstemp' . clang-analyzer-security.insecureAPI.mkstemp (alias) Clang Static Analyzer Available Checkers . clang-analyzer-security.insecureAPI.mktemp 'mktemp' . clang-analyzer-security.insecureAPI.mktemp (alias) Clang Static Analyzer Available Checkers . clang-analyzer-security.insecureAPI.rand 'rand' 'random' . clang-analyzer-security.insecureAPI.rand (alias) Clang Static Analyzer Available Checkers . clang-analyzer-security.insecureAPI.strcpy 'strcpy' 'strcat' . clang-analyzer-security.insecureAPI.strcpy (alias) Clang Static Analyzer Available Checkers . clang-analyzer-security.insecureAPI.vfork 'vfork' . clang-analyzer-security.insecureAPI.vfork (alias) Clang Static Analyzer Available Checkers . clang-analyzer-unix.API UNIX/Posix . clang-analyzer-unix.API (alias) Clang Static Analyzer Available Checkers . clang-analyzer-unix.BlockInCriticalSection (blocking) (critical section) . clang-analyzer-unix.BlockInCriticalSection (alias) Clang Static Analyzer Available Checkers . clang-analyzer-unix.Errno 'errno' . clang-analyzer-unix.Errno (alias) Clang Static Analyzer Available Checkers . clang-analyzer-unix.Malloc (memory leaks) (double free) (use-after-free) . malloc()/free() . clang-analyzer-unix.Malloc (alias) Clang Static Analyzer Available Checkers . clang-analyzer-unix.MallocSizeof malloc sizeof . clang-analyzer-unix.MallocSizeof (alias) Clang Static Analyzer Available Checkers . clang-analyzer-unix.MismatchedDeallocator (deallocators) . clang-analyzer-unix.MismatchedDeallocator (alias) Clang Static Analyzer Available Checkers . clang-analyzer-unix.StdCLibraryFunctions C . clang-analyzer-unix.StdCLibraryFunctions (alias) Clang Static Analyzer Available Checkers . clang-analyzer-unix.Stream (stream) . clang-analyzer-unix.Stream (alias) Clang Static Analyzer Available Checkers . clang-analyzer-unix.Vfork vfork . clang-analyzer-unix.Vfork (alias) Clang Static Analyzer Available Checkers . clang-analyzer-unix.cstring.BadSizeArg C . clang-analyzer-unix.cstring.BadSizeArg (alias) Clang Static Analyzer Available Checkers . clang-analyzer-unix.cstring.NullArg (null) C . clang-analyzer-unix.cstring.NullArg (alias) Clang Static Analyzer Available Checkers . clang-analyzer-webkit.NoUncountedMemberChecker (uncounted) . clang-analyzer-webkit.NoUncountedMemberChecker (alias) Clang Static Analyzer Available Checkers . clang-analyzer-webkit.RefCntblBaseVirtualDtor (ref-countable) (virtual destructor) . clang-analyzer-webkit.RefCntblBaseVirtualDtor Clang Static Analyzer Available Checkers . clang-analyzer-webkit.UncountedLambdaCapturesChecker (captures) . clang-analyzer-webkit.UncountedLambdaCapturesChecker Clang Static Analyzer Available Checkers . concurrency-mt-unsafe (thread-unsafe) . ( gmtime(3)) (racy) . FunctionSet . thread-unsafe ( setenv(3)) ( ) . : // 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(); : tm = gmtime(timep); // uses a global buffer sleep(1); // implementation may use SIGALRM FunctionSet libc posix glibc any. posix thread-unsafe POSIX . POSIX.1-2001 <<2.9.1 Thread-Safety>> thread-unsafe . Glibc thread-safe ( dirname(3)) POSIX ( getopt_long(3)). Glibc GNU MT-Safe : API thread-unsafe libc libc any () . concurrency-thread-canceltype-asynchronous pthread_setcanceltype (asynchronous) . (PTHREAD_CANCEL_ASYNCHRONOUS) PTHREAD_CANCEL_DEFERRED . (deferred) . pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldtype); CERT C : POS47-C. Do not use threads that can be canceled asynchronously . cert-pos47-c . cppcoreguidelines-avoid-c-arrays cppcoreguidelines-avoid-c-arrays modernize-avoid-c-arrays <> . cppcoreguidelines-avoid-capturing-lambda-coroutines C++20 use-after-free (closure) . CP.51 C++ Core Guidelines . (capture lists) (suspension point) . (refcounted) . closure (scope) . closure . closure use-after-free . : int value = get_value(); std::shared_ptr sharedFoo = get_foo(); { const auto lambda = [value, sharedFoo]() -> std::future { 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 : value sharedFoo. lambda() closure . closure . use-after-free . closure use-after-free . C++20 captures closure . C++ . cppcoreguidelines-avoid-const-or-ref-data-members const (lvalue rvalue) . (copy-constructible) (copy-assignable) . : // 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 x; std::shared_ptr x; gsl::not_null x; }; // Bad, rvalue reference member struct RefRef { int&& x; }; C.12 C++ Core Guidelines . : Data members: Never const . cppcoreguidelines-avoid-do-while do-while . while . . ES.75 C++ Core Guidelines . : int x; do { std::cin >> x; // ... } while (x < 0); IgnoreMacros . : #define FOO_BAR(x) \ do { \ foo(x); \ bar(x); \ } while(0) false . cppcoreguidelines-avoid-goto goto . . ES.76 C++ Core Guidelines 6.3.1 High Integrity C++ Coding Standard . goto A Case against the GO TO Statement : . goto . C/C++ . // 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(); C++ goto . 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(); goto C++ . IgnoreMacros true goto . false . cppcoreguidelines-avoid-magic-numbers cppcoreguidelines-avoid-magic-numbers readability-magic-numbers <> . cppcoreguidelines-avoid-non-const-global-variables -const I.2 C++ Core Guidelines . R.6 C++ Core Guidelines I.2 . 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; }; a c c_ptr1 c_const_ptr c_reference -const -const . AllowInternalLinkage true -const (anonymous namespaces) . false . AllowThreadLocal true -const - (thread-local storage duration) . false . cppcoreguidelines-avoid-reference-coroutine-parameters (coroutine) . (suspend point) (dangling) . (by value) . : std::future someCoroutine(int& val) { co_await ...; // When the coroutine is resumed, 'val' might no longer be valid. if (val) ... } CP.53 C++ Core Guidelines . cppcoreguidelines-c-copy-assignment-signature cppcoreguidelines-c-copy-assignment-signature misc-unconventional-assign-operator <> . cppcoreguidelines-explicit-virtual-functions cppcoreguidelines-explicit-virtual-functions modernize-use-override <> . cppcoreguidelines-init-variables . . (Type.5) ES.20 C++ Core Guidelines . float double . (fix) . float double NaN . : void function() { int x; char *txt; double d; // Rest of the function. } : #include void function() { int x = 0; char *txt = nullptr; double d = NAN; // Rest of the function. } enum 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 } IncludeStyle include llvm google. llvm . MathHeader NAN . . cppcoreguidelines-interfaces-global-init (globals) extern (order-of-initialization) . I.22 C++ Core Guidelines . constexpr . cppcoreguidelines-macro-to-enum cppcoreguidelines-macro-to-enum (alias) modernize-macro-to-enum <> . cppcoreguidelines-macro-usage . C++ Core Guidelines ES.31 ES.32 . : #define C 0 #define F1(x, y) ((a) > (b) ? (a) : (b)) #define F2(...) (__VA_ARGS__) #define F3(x, y) x##y #define COMMA , #define NORETURN [[noreturn]] #define DEPRECATED attribute((deprecated)) #if LIB_EXPORTS #define DLLEXPORTS __declspec(dllexport) #else #define DLLEXPORTS __declspec(dllimport) #endif : 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__) ^ AllowedRegexp (regular expression) . DEBUG*|LIBTORRENT*|TORRENT*|UNI* libtorrent . ^DEBUG_* . CheckCapsOnly (CAPS_ONLY) . . false . IgnoreCommandLineMacros . true . cppcoreguidelines-misleading-capture-default-by-value (by-value) this . . [=] this . this . [=] . : 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 } }; F.54 C++ Core Guidelines . cppcoreguidelines-missing-std-forward (forwarding reference) . : template void wrapper(T&& t) { impl(std::forward(t), 1, 2); // Correct } template void wrapper2(T&& t) { impl(t, 1, 2); // Oops - should use std::forward(t) } template void wrapper3(T&& t) { impl(std::move(t), 1, 2); // Also buggy - should use std::forward(t) } template void wrapper_function(F&& f) { std::forward(f)(1, 2); // Correct } template void wrapper_function2(F&& f) { f(1, 2); // Incorrect - may not invoke the desired qualified function operator } ForwardFunction . ::std::forward . F.19 C++ Core Guidelines . cppcoreguidelines-narrowing-conversions ES.46 C++ Core Guidelines . cppcoreguidelines-narrowing-conversions (alias) bugprone-narrowing-conversions <> . cppcoreguidelines-no-malloc C malloc() realloc() calloc() free() . RAII . ( posix_memalign()) . R.10 C++ Core Guidelines . (fix-it hints) 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)); Allocations (semicolon) (fully qualified) . ::malloc;::calloc . Deallocations . ::free . Reallocations . ::realloc . cppcoreguidelines-no-suspend-with-lock (coroutines) lock guard (scope) . mutex lock guard . mutex (deadlock) . . lock_guard mutex std::mutex::lock() . : 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 } CP.52 C++ Core Guidelines . cppcoreguidelines-noexcept-destructor C.37 C++ Core Guidelines . cppcoreguidelines-noexcept-destructor performance-noexcept-destructor <> . cppcoreguidelines-noexcept-move-operations C.66 C++ Core Guidelines . cppcoreguidelines-noexcept-move-operations performance-noexcept-move-constructor <> . cppcoreguidelines-noexcept-swap C.83 C.84 C.85 C++ Core Guidelines . cppcoreguidelines-noexcept-swap check performance-noexcept-swap <> . cppcoreguidelines-non-private-member-variables-in-classes cppcoreguidelines-non-private-member-variables-in-classes misc-non-private-member-variables-in-classes <> . cppcoreguidelines-owning-memory gsl::owner RAII . I.11 C.33 R.3 GSL.Views C++ Core Guidelines . gsl::owner namespace gsl { template owner = T; } Guideline Support Library . () (flow sensitive) . . new malloc() . // Creating an owner with factory functions is checked. gsl::owner function_that_returns_owner() { return gsl::owner(new int(42)); } // Dynamic memory must be assigned to an owner int* Something = new int(42); // BAD, will be caught gsl::owner Owner = new int(42); // Good gsl::owner 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 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 Owned = &Stack; // Bad, not a resource assigned gsl::owner (delete) . // 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 Owner = new int(42); // Good delete Owner; // Good as well, statically enforced, that only owners get deleted gsl::owner gsl::owner . void expects_owner(gsl::owner o) { delete o; } // Bad Code int NonOwner = 42; expects_owner(&NonOwner); // Bad, will get caught // Good Code gsl::owner 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 = 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 LegacyResourceProducers - (semicolon) (legacy) gsl::owner<> . : ::malloc;::aligned_alloc;::realloc;::calloc;::fopen;::freopen;::tmpfile. LegacyResourceConsumers - gsl::owner<> . : ::free;::realloc;::freopen;::fclose. gsl::owner typedef alias . using heap_int = gsl::owner; heap_int allocated = new int(42); // False positive! gsl::owner (templated type alias) . (template) . gsl::owner (false positive) . : o std::exchange o std::vector> // This template function works as expected. Type information doesn't get lost. template void delete_owner(gsl::owner owned_object) { delete owned_object; // Everything alright } gsl::owner function_that_returns_owner() { return gsl::owner(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 void bad_template_function(T some_object) { // This line will trigger the warning, that a non-owner is assigned to an owner gsl::owner new_owner = some_object; } // Calling the function with an owner still yields a false positive. bad_template_function(gsl::owner(new int(42))); // The same issue occurs with templated classes like the following. template class OwnedValue { public: const T getValue() const { return _val; } private: T _val; }; // Code, that yields a false positive. OwnedValue> Owner(new int(42)); // Type deduction yield T -> int * // False positive, getValue returns int* and not gsl::owner gsl::owner OwnedInt = Owner.getValue(); . : // Two owners with assigned resources gsl::owner Owner1 = new int(42); gsl::owner Owner2 = new int(42); Owner2 = Owner1; // Conceptual Leak of initial resource of Owner2! Owner1 = nullptr; gsl::owner std::unique_ptr gsl::owner (move) Owner2 . (flow-sensitive analysis) . Clang Static Analyzer . cppcoreguidelines-prefer-member-initializer (member initializers) . . . C.49 C++ Core Guidelines . C.48 C++ Core Guidelines . modernize-use-default-member-init <> . class C { int n; int m; public: C() { n = 1; // Literal in default constructor if (dice()) return; m = 1; } }; n m m (if) : class C { int n; int m; public: C(): n(1) { if (dice()) return; m = 1; } }; class C { int n; int m; public: C(int nn, int mm) { n = nn; // Neither default constructor nor literal if (dice()) return; m = mm; } }; m n m (if) : C(int nn, int mm) : n(nn) { if (dice()) return; m = mm; } cppcoreguidelines-pro-bounds-array-to-pointer-decay (decay) . . span (bounds-checked) . (Bounds 3) C++ Core Guidelines . cppcoreguidelines-pro-bounds-avoid-unchecked-container-access operator[] STL . at STL at GSL begin() end() range-for std::span . std::vector a; int b = a[4]; std::unique_ptr a; int b = a[0]; . STL operator[] (: std::map::operator[]). SL.con.3 (Bounds 4) C++ Core Guidelines . ExcludeClasses - (regex) . : ::std::map;::std::unordered_map;::std::flat_map. FixMode . none at ( a.at(index) ) function ( f(a, index)). none . FixFunction function . C++23 a[] f(a) . FixFunctionEmptyArgs . gsl::at . FixFunctionEmptyArgs function C++23 . . . FixFunction . cppcoreguidelines-pro-bounds-constant-array-index std::array ( std::array) . -Warray-bounds Clang . (Bounds 2) C++ Core Guidelines . gsl::at . GslHeader include gsl::at() ( "gsl/gsl.h") . . IncludeStyle include : llvm google. llvm . cppcoreguidelines-pro-bounds-pointer-arithmetic (pointer arithmetic) . . . span . (Bounds 1) C++ Core Guidelines . AllowIncrementDecrementOperators / . false . cppcoreguidelines-pro-type-const-cast const_cast C++ . StrictMode <#cmdoption-arg- StrictMode> const_cast const volatile . C++ const (undefined behavior) const_cast . C++ const . volatile C++ . . volatile . Type safety (Type 3) ES.50: Don't cast away const C++ Core Guidelines . StrictMode true const_cast . false const volatile . false . cppcoreguidelines-pro-type-cstyle-cast C (C-style casts) (downcast) static_cast const_cast reinterpret_cast . (type safety) X Z . C (T)expression : const_cast static_cast static_cast const_cast reinterpret_cast reinterpret_cast const_cast . (T)expression . Type safety (Type.4) C++ Core Guidelines . cppcoreguidelines-pro-type-member-init ( ) . . C++11 . (initializer list) . . (false positive) . . {} C++11 = {} . IgnoreArrays true . . false . UseAssignment true ( int i = 0; ) ( int i{}; ) . false . Type safety (Type.6) C++ Core Guidelines . cppcoreguidelines-pro-type-reinterpret-cast reinterpret_cast C++ . X Z . Type safety (Type.1.1) C++ Core Guidelines . cppcoreguidelines-pro-type-static-cast-downcast static_cast . dynamic_cast . X Z . Type safety (Type.2) C++ Core Guidelines . StrictMode false (non-polymorphic) . true . cppcoreguidelines-pro-type-union-access union . union . union union (nontrivial destructor) . . Type safety (Type.7) C++ Core Guidelines . cppcoreguidelines-pro-type-vararg C (vararg) va_arg . vararg SFINAE 0 vararg (unevaluated context) . vararg . . Type safety (Type.8) C++ Core Guidelines . cppcoreguidelines-rvalue-reference-param-not-moved rvalue (move) . rvalue std::move . . : void logic(std::string&& Input) { std::string Copy(Input); // Oops - forgot to std::move } . : void conditional_use([[maybe_unused]] std::string&& Input) { // No diagnostic here since Input is unused and marked as such } AllowPartialMove true std::move . CppCoreGuideline F.18 (move) . false . // 'p' is flagged by this check if and only if AllowPartialMove is false void move_members_of(pair&& p) { pair 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&& p) { pair other = std::move(p); } IgnoreUnnamedParams true rvalue . false . IgnoreNonDeducedTemplateTypes true rvalue (non-deduced) . false . template 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 void forwarding_ref(T&& t) { T other = std::forward(t); } MoveFunction (move) . ::std::move . F.18 C++ Core Guidelines : cppcoreguidelines-slicing (slicing) vtable . : ( ) . : 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. ES.63 C.145 C++ Core Guidelines . cppcoreguidelines-special-member-functions . . . (default) . = delete . C.21 C++ Core Guidelines : AllowSoleDefaultDtor true ( false ) (default) . 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 true ( false ) . . : struct A { A(const A&); A& operator=(const A&); ~A(); }; AllowMissingMoveFunctionsWhenCopyIsDeleted true ( false ) (delete) . Copyable and Movable Types . : struct A { A(const A&) = delete; A& operator=(const A&) = delete; ~A(); }; AllowImplicitlyDeletedCopyOrMove true ( false ) . : struct A : boost::noncopyable { ~A() { std::cout << "dtor\n"; } }; IgnoreMacros true . true . cppcoreguidelines-use-default-member-init C.48 C++ Core Guidelines . cppcoreguidelines-use-default-member-init modernize-use-default-member-init <> . cppcoreguidelines-use-enum-class enum ( unscoped) enum class . Enum.3 C++ Core Guidelines . : enum E {}; // use "enum class E {};" instead enum class E {}; // OK struct S { enum E {}; // use "enum class E {};" instead // OK with option IgnoreUnscopedEnumsInClasses }; namespace N { enum E {}; // use "enum class E {};" instead } IgnoreUnscopedEnumsInClasses (true) enum . false . cppcoreguidelines-virtual-class-destructor ("public and virtual") ("protected and non-virtual") . (undefined behavior) . C.35 C++ Core Guidelines . . . (private) . / 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(){} }; : 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 OSSpinlock (livelock) . : o OSSpinlockLock o OSSpinlockTry o OSSpinlockUnlock OSSpinlock: darwin-dispatch-once-nonstatic dispatch_once_t (static) . dispatch_once_t (automatic) libdispatch . static dispatch_once_t (stack) . dispatch_once_t (lazy) libdispatch . dispatch_once . fuchsia-default-arguments-calls . : int foo(int value = 5) { return value; } . : foo(); // warning foo(0); // no warning Fuchsia . fuchsia-default-arguments-declarations . : int foo(int value = 5) { return value; } . Fuchsia : fuchsia-header-anon-namespaces fuchsia-header-anon-namespaces (alias) misc-anonymous-namespace-in-header <> . fuchsia-multiple-inheritance fuchsia-multiple-inheritance misc-multiple-inheritance <> . Fuchsia : fuchsia-overloaded-operator (overload ) ( ) . : int operator+(int); // Warning B &operator=(const B &Other); // No warning B &operator=(B &&Other) // No warning Fuchsia : fuchsia-statically-constructed-objects (non-trivial) (static storage) constexpr . : 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 Fuchsia : fuchsia-temporary-objects Zircon . (fully qualified) . "Foo" "NS::Bar" : Foo(); Foo F = Foo(); func(Foo()); namespace NS { Bar(); } : 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 . . class Derived : Foo {} // Derived is not explicitly disallowed Derived(); // and so temporary construction is okay Names (semi-colon) C++ . . fuchsia-trailing-return (trailing return) decltype . : // int add_one(const int arg) { return arg; } // auto get_add_one() -> int (*)(const int) { return add_one; } decltype : // auto lambda = [](double x, double y) -> double {return x + y;}; // template auto fn(const T1 &lhs, const T2 &rhs) -> decltype(lhs + rhs) { return lhs + rhs; } Fuchsia : fuchsia-virtual-inheritance (virtual inheritance) . : class B : public virtual A {}; // Fuchsia : google-build-explicit-make-pair make_pair (deduce) . G++ 4.6 C++11 make_pair . cpplint.py : build/explicit_make_pair. google-build-namespaces google-build-namespaces misc-anonymous-namespace-in-header <> . (anonymous namespaces) . cpplint.py : build/namespaces. google-build-using-namespace using namespace . Google C++ : using-directive . // -- . using namespace foo; cpplint.py : build/namespaces. google-default-arguments (virtual methods) . : google-explicit-constructor explicit . : struct S { int x; operator bool() const { return true; } }; bool f() { S a{1}; S b{2}; return a == b; } true bool . explicit . initializer_list explicit . : struct S { S(int a); explicit S(const S&); operator bool() const; ... : struct S { explicit S(int a); S(const S&); explicit operator bool() const; ... : google-global-names-in-headers (global namespace pollution) . using . : . google-objc-avoid-nsobject-new +new (override) Objective-C . Objective-C +new +alloc -init . : NSDate *now = [NSDate new]; Foo *bar = [Foo new]; +alloc/-init (class factory methods) . NSDate *now = [NSDate date]; Foo *bar = [[Foo alloc] init]; Do Not Use +new Objective-C . google-objc-avoid-throwing-exception (throwing exceptions) Objective-C . C++ Objective-C . C++: NSError ** BOOL . : - (void)readFile { if ([self isError]) { @throw [NSException exceptionWithName:...]; } } NSError ** : - (BOOL)readFileWithError:(NSError **)error { if ([self isError]) { *error = [NSError errorWithDomain:...]; return NO; } return YES; } : google-objc-function-naming Objective-C Objective-C . : Pascal case . (storage class) static . : static bool is_positive(int i) { return i > 0; } bool IsNegative(int i) { return i < 0; } : static bool IsPositive(int i) { return i > 0; } bool *ABCIsNegative(int i) { return i < 0; } google-objc-global-variable-declaration Objective-C Objective-C . : g[A-Z].* () k[A-Z].* () . . : static NSString* myString = @"hello"; : static NSString* gMyString = @"hello"; : static NSString* const myConstString = @"hello"; : static NSString* const kMyConstString = @"hello"; : static NSString* __anotherString = @"world"; . . google-readability-avoid-underscore-in-googletest-name (underscore) (test suite) (googletest) : o TEST o TEST_F o TEST_P o TYPED_TEST o TYPED_TEST_P FRIEND_TEST . : TEST(TestSuiteName, Illegal_TestName) {} TEST(Illegal_TestSuiteName, TestName) {} . . DISABLED_ . (fix) . google-readability-braces-around-statements google-readability-braces-around-statements readability-braces-around-statements <> . google-readability-casting google-readability-casting modernize-avoid-c-style-cast <> . C (C-style casts) . cpplint.py : readability/casting. google-readability-function-size google-readability-function-size readability-function-size <> . google-readability-namespace-comments google-readability-namespace-comments llvm-namespace-comment <> . google-readability-todo TODO . : . cpplint.py : readability/todo Style TODO (fix-it hints) . Hyphen Parentheses. Hyphen . o Hyphen : // TODO: username - details. o Parentheses : // TODO(username): details. google-runtime-float long double (portability) . : google-runtime-int short long long long u?intXX(_t)? . : . cpplint.py : runtime/int. UnsignedTypePrefix (unsigned) . uint . SignedTypePrefix (signed) . int . TypeSuffix . . google-runtime-operator operator & . cpplint.py : runtime/operator. google-upgrade-googletest-case API 1.9 Google Test case API suite . case "test case" "test suite" (ISTQB) ISO 29119 . Google Test 1.9 ( ) . 1.9 . API : o testing::Test testing::TestInfo testing::TestEventListener testing::UnitTest o TYPED_TEST_CASE TYPED_TEST_CASE_P REGISTER_TYPED_TEST_CASE_P INSTANTIATE_TYPED_TEST_CASE_P o testing::TestCase : class FooTest : public testing::Test { public: static void SetUpTestCase(); static void TearDownTestCase(); }; TYPED_TEST_CASE(BarTest, BarTypes); : class FooTest : public testing::Test { public: static void SetUpTestSuite(); static void TearDownTestSuite(); }; TYPED_TEST_SUITE(BarTest, BarTypes); . (template) . hicpp-avoid-c-arrays hicpp-avoid-c-arrays (alias) modernize-avoid-c-arrays <> . 4.1.1 . hicpp-avoid-goto hicpp-avoid-goto cppcoreguidelines-avoid-goto <> . 6.3.1 . hicpp-braces-around-statements hicpp-braces-around-statements readability-braces-around-statements <> . 6.1.1 . hicpp-deprecated-headers hicpp-deprecated-headers modernize-deprecated-headers <> . 1.3.3 . hicpp-exception-baseclass throw std::exception . 15.1 High Integrity C++ . 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 google-explicit-constructor <> . 5.4.1 . explicit . (casting) . : o cppcoreguidelines-pro-type-static-cast-downcast <> o cppcoreguidelines-pro-type-reinterpret-cast <> o cppcoreguidelines-pro-type-const-cast <> o cppcoreguidelines-pro-type-cstyle-cast <> hicpp-function-size readability-function-size <> . . o 8.2.2 o 8.3.1 o 8.3.2 hicpp-ignored-remove-result 17.5.1 std::remove std::remove_if std::unique . std::remove std::remove_if std::unique (swap move) . (iterator) . std::erase . bugprone-unused-return-value <> . AllowCastToVoid void . : true. hicpp-invalid-access-moved bugprone-use-after-move <> . 8.4.1 (moved-from) . hicpp-member-init cppcoreguidelines-pro-type-member-init <> . 12.4.2 . hicpp-move-const-arg hicpp-move-const-arg performance-move-const-arg <> . 17.3.1 . hicpp-multiway-paths-covered . switch if . 6.1.2 6.1.4 High Integrity C++ . if-else if else . else . . void f1() { int i = determineTheNumber(); if(i > 0) { // Some Calculation } else if (i < 0) { // Precondition violated or something else. } // ... } switch . // 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 } 6.1.4 switch case default . switch if . (degenerated) switch . // 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) {} WarnOnMissingElse else . false . hicpp-named-parameter readability-named-parameter <> . 8.2.1 . hicpp-new-delete-operators misc-new-delete-overloads <> . 12.3.1 new delete . hicpp-no-array-decay hicpp-no-array-decay cppcoreguidelines-pro-bounds-array-to-pointer-decay <> . 4.1.1 . hicpp-no-assembler . . 7.5.1 High Integrity C++ Coding Standard . hicpp-no-malloc hicpp-no-malloc cppcoreguidelines-no-malloc <> . 5.3.2 . hicpp-noexcept-move performance-noexcept-move-constructor <> . 12.5.4 noexcept . hicpp-signed-bitwise . High Integrity C++ Standard 5.6.1 . IgnorePositiveIntegerLiterals true ~0 2 << 1 . false . hicpp-special-member-functions cppcoreguidelines-special-member-functions <> . 12.5.7 . hicpp-static-assert hicpp-static-assert misc-static-assert <> . 7.1.10 . hicpp-undelegated-constructor bugprone-undelegated-constructor <> . 12.4.5 . 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 hicpp-uppercase-literal-suffix readability-uppercase-literal-suffix <> . 4.2.1 U . hicpp-use-auto hicpp-use-auto modernize-use-auto <> . 7.1.8 . hicpp-use-emplace hicpp-use-emplace modernize-use-emplace <> . 17.4.2 . hicpp-use-equals-default modernize-use-equals-default <> . 12.5.1 (default) . hicpp-use-equals-delete modernize-use-equals-delete <> . 12.5.1 (delete) . hicpp-use-noexcept hicpp-use-noexcept modernize-use-noexcept <> . 1.3.5 . hicpp-use-nullptr hicpp-use-nullptr modernize-use-nullptr <> . 2.5.3 . hicpp-use-override modernize-use-override <> . 10.2.1 (overriding) override . hicpp-vararg hicpp-vararg cppcoreguidelines-pro-type-vararg <> . 14.1.1 . linuxkernel-must-check-errs linux/err.h . . ERR_PTR PTR_ERR IS_ERR IS_ERR_OR_NULL ERR_CAST PTR_ERR_OR_ZERO . __attribute__((warn_unused_result)) clang . : /* 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 llvm-else-after-return (alias) readability-else-after-return <> . llvm-header-guard (header guards) LLVM . llvm-include-order #include . : llvm-namespace-comment google-readability-namespace-comments . (namespaces) . namespace n1 { void f(); } // becomes namespace n1 { void f(); } // namespace n1 Options ShortNamespaceLines ShortNamespaceLines . 1U . SpacesBeforeComments (spaces) . 1U . AllowOmittingNamespaceComments true . . false . llvm-prefer-isa-or-dyn-cast-in-conditionals cast<> (null pointer) (assert) dyn_cast<> . var && isa(var) var . // Finds these: if (auto x = cast(y)) {} // is replaced by: if (auto x = dyn_cast(y)) {} if (cast(y)) {} // is replaced by: if (isa(y)) {} if (dyn_cast(y)) {} // is replaced by: if (isa(y)) {} if (var && isa(var)) {} // is replaced by: if (isa_and_nonnull(var.foo())) {} // Other cases are ignored, e.g.: if (auto f = cast(y)->foo()) {} if (cast(y)->foo()) {} if (X.cast(y)) {} llvm-prefer-register-over-unsigned unsigned vreg physreg Register . (implicit cast) Register unsigned . void example(MachineOperand &MO) { unsigned Reg = MO.getReg(); ... } : void example(MachineOperand &MO) { Register Reg = MO.getReg(); ... } llvm-prefer-static-over-anonymous-namespace (anonymous namespace) static . LLVM . static (visibility) . : namespace { class StringSort { public: StringSort(...) bool operator<(const char *RHS) const; }; // warning: place method definition outside of an anonymous namespace bool StringSort::operator<(const char *RHS) const {} // warning: prefer using 'static' for restricting visibility void runHelper() {} // warning: prefer using 'static' for restricting visibility int myVariable = 42; } : // Small anonymous namespace for class declaration namespace { class StringSort { public: StringSort(...) bool operator<(const char *RHS) const; }; } // placed method definition outside of the anonymous namespace bool StringSort::operator<(const char *RHS) const {} // used 'static' instead of an anonymous namespace static void runHelper() {} // used 'static' instead of an anonymous namespace static int myVariable = 42; AllowVariableDeclarations true (anonymous namespace) . true . AllowMemberFunctionsInClass true . true . llvm-qualified-auto llvm-qualified-auto (alias) readability-qualified-auto <> . llvm-twine-local Twine (use after free) . static Twine Moo = Twine("bark") + "bah"; // becomes static std::string Moo = (Twine("bark") + "bah").str(); Twine Twine . static Twine getModuleIdentifier(StringRef moduleName) { return moduleName + "_module"; } void foo() { Twine result = getModuleIdentifier(std::string{"abc"} + "def"); // temporary std::string is destroyed here, result is dangling } (fix-it) Twine std::string . Twine std::string . llvm-mlir-op-builder OpBuilder::create MLIR T::create . builder.create(builder.getUnknownLoc(), "baz"); : FooOp::create(builder, builder.getUnknownLoc(), "baz"); llvm-use-ranges (iterator) STL (range-based) LLVM llvm/ADT/STLExtras.h . auto it = std::find(vec.begin(), vec.end(), value); bool all = std::all_of(vec.begin(), vec.end(), [](int x) { return x > 0; }); : auto it = llvm::find(vec, value); bool all = llvm::all_of(vec, [](int x) { return x > 0; }); STL : std::all_of, std::any_of, std::binary_search, std::copy, std::copy_if, std::count, std::count_if, std::equal, std::fill, std::find, std::find_if, std::find_if_not, std::for_each, std::includes, std::is_sorted, std::lower_bound, std::max_element, std::min_element, std::mismatch, std::none_of, std::partition, std::partition_point, std::remove_if, std::replace, std::stable_sort, std::transform, std::uninitialized_copy, std::unique, std::upper_bound. #include "llvm/ADT/STLExtras.h" . llvmlibc-callee-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 llvm-libc . // Implementation inside the LIBC_NAMESPACE_DECL namespace. // Correct if: // - LIBC_NAMESPACE_DECL is a macro // - LIBC_NAMESPACE_DECL expansion starts with `[[gnu::visibility("hidden")]] __llvm_libc` namespace LIBC_NAMESPACE_DECL { void LLVM_LIBC_ENTRYPOINT(strcpy)(char *dest, const char *src) {} // Namespaces within LIBC_NAMESPACE_DECL 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_DECL namespace. void LLVM_LIBC_ENTRYPOINT(strcpy)(char *dest, const char *src) {} // Incorrect: outer most namespace is not the LIBC_NAMESPACE_DECL macro. namespace something_else { void LLVM_LIBC_ENTRYPOINT(strcpy)(char *dest, const char *src) {} } // Incorrect: outer most namespace expansion does not start with `[[gnu::visibility("hidden")]] __llvm_libc`. #define LIBC_NAMESPACE_DECL custom_namespace namespace LIBC_NAMESPACE_DECL { void LLVM_LIBC_ENTRYPOINT(strcpy)(char *dest, const char *src) {} } llvmlibc-inline-function-decl inline LIBC_INLINE (deleted). libc . llvmlibc-restrict-system-libc-headers include libc llvm-libc . #include // Not allowed because it is part of system libc. #include // Allowed because it is provided by the compiler. #include "internal/stdio.h" // Allowed because it is NOT part of system libc. include libc . libc dirent llvm-libc . ABI . Includes (glob) include . -checks clang-tidy (wildcard) * - . -* include . include . portability-restrict-system-includes <> . misc-anonymous-namespace-in-header (anonymous) . (ODR One Definition Rule) include . (link-time) . CERT C++ DCL59-CPP. Do not define an unnamed namespace in a header file . cpplint.py: build/namespaces. misc-confusable-identifiers . CVE-2021-42574 . : 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 const . const : ES.25 C++ Core Guidelines. (type-based) . (handle) -const (scope) 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 (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 analyzed. int *pointer_variable = &potential_const_int; // Before transformation int const*const pointer_variable = &potential_const_int; // After transformation, both pointer itself and pointee are supported. int last_copy = *pointer_variable; . readability-isolate-declaration <> . cppcoreguidelines-avoid-non-const-global-variables <> const (globals) . C . (templated) (instantiation dependent) . const . (translation unit) . AnalyzeValues int i = 42;. true . // 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 int &ref = i;. true . int i = 42; // Warning int& ref = i; // No warning int const& ref = i; AnalyzePointers int *ptr = &i;. WarnPointersAsValues WarnPointersAsPointers . true . WarnPointersAsValues const . const : . false . int value = 42; // Warning const int * pointer_variable = &value; // No warning const int *const pointer_variable = &value; WarnPointersAsPointers const . true . AnalyzePointers true . int value = 42; // No warning const int *const pointer_variable = &value; // Warning int *const pointer_variable = &value; TransformValues (fixit-hints) const . true . // 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 (fixit-hints) const . true . // 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 (fixit-hints) . ! false . 'WarnPointersAsValues' '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; TransformPointersAsPointers (fix-it hints) . false . WarnPointersAsPointers true . int value = 42; // Before int * pointer_variable = &value; // After const int * pointer_variable = &value; // Before int * a[] = {&value, &value}; // After const int * a[] = {&value, &value}; AllowedTypes - (semicolon) const . (regex) [Rr]ef(erence)?$ Ref ref Reference reference . :: ( namespace::Type) ( Type) . . misc-coroutine-hostile-raii RAII (suspension points) (coroutine) . (scoped-lockable) (denylist) . (thread) . << >> . C++20 co_await (resumed) . co_await co_yield . . : o Scoped-lockable: scoped-lockable . (undefined behaviour) . scoped_lockable . o (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(); } RAIITypesList - (qualified types) . : my::lockable;a::b;::my::other::lockable std::lock_guard;std::scoped_lock . AllowedAwaitablesList - awaitable RAII (scope) (await) . co_await awaitable awaitable . RAII co_await (flag) . : // 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(); } : my::safe::awaitable;other::awaitable . AllowedCallees - (callee) RAII . : // Consider option AllowedCallees = "noop" task noop() { co_return; } task coro() { // This persists across the co_await but is not flagged // because the awaitable is considered safe to await on. const std::lock_guard l(&mu_); co_await noop(); } : my::safe::await;other::await . misc-definitions-in-headers extern inline include (translation units) ODR ( ) . // 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 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 struct B { void f1(); }; // OK: member function definition of a class template is allowed. template void B::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 constexpr T pi = T(3.1415926L); clang-tidy --fix-notes inline . inline . misc-header-include-cycle #include . // 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 ++C . . . << include>> . include A B include B ( include ) A include . . include . . include . . . include . include include . #include . . include . . IgnoredFilesList / . - (semicolon) . //NOLINT . . misc-include-cleaner include . (translation unit) . . : // 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" IgnoreHeaders regex - / regex . foo/.* / foo . . DeduplicateFindings . true . UnusedIncludes include (include ) . true . MissingIncludes include ( include ) . true . misc-misleading-bidirectional (bidirectional) Trojan Source . : #include 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 Trojan Source . : #include 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 const (pointee) typedef/ using const . int * const 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 } typedef/using const . const ( ) . misc-multiple-inheritance (pure virtual) . (concrete) : 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 {}; : 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; } }; Fuchsia : misc-new-delete-overloads cert-dcl54-cpp . (overloaded) new() delete() (free store) . (non-placement) new() delete() . (deleted) (private) (placement) . DCL54-CPP CERT C++ : Overload allocation and deallocation functions as a pair in the same scope . misc-no-recursion ( SCC ) ( recursion) . : o CERT C++ DCL56-CPP: Avoid cycles during initialization of static objects . o JPL C (JPL DOCID D-60411) 2.4 Do not use direct or indirect recursion. o OpenCL 1.2 6.9 Restrictions: i. Recursion is not supported. . o o C++ misc-non-copyable-objects cert-fio38-c . (dereferences) (by value) FILE C pthread_mutex_t POSIX . FIO38-C CERT C++ : Do not copy a FILE object . misc-non-private-member-variables-in-classes cppcoreguidelines-non-private-member-variables-in-classes . public . private . IgnoreClassesWithAllMemberVariablesBeingPublic true public . false . IgnorePublicMemberVariables true ( ) public . false . misc-override-with-different-visibility (overrides) (visibility) . private public . public protected private . (destructors) . using . class A { public: virtual void f_pub(); private: virtual void f_priv(); }; class B: public A { public: void f_priv(); // warning: changed visibility from private to public private: void f_pub(); // warning: changed visibility from public to private }; class C: private A { // no warning: f_pub becomes private in this case but this is from the // private inheritance }; class D: private A { public: void f_pub(); // warning: changed visibility from private to public // 'f_pub' would have private access but is forced to be // public }; . (private) (public) . (private inheritance) . (protected) (public) ( ) using . DisallowedVisibilityChange . any widening narrowing. widening (private) (public) . any . CheckDestructors true . . false . CheckOperators true C++ ( ) . ( ) . . false . IgnoredFunctions . - (semicolon) . (regular expressions) ( MyClass::.*) ( my_function ::.*::my_function) . . . misc-predictable-rand std::rand() . . std::rand() () . (seed) . CERT C : MSC30-C. Do not use the rand() function for generating pseudorandom numbers . MSC50-CPP. Do not use std::rand() for generating pseudorandom numbers . misc-redundant-expression - . : o o true o false o ( ) . : ((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 int b = a | 4 | a // identical expr on both sides ((x=1) | (x=1)) // expression is identical (DEFINE_1 | DEFINE_1) // same macro on the both sides ((DEF_1 + DEF_2) | (DEF_1+DEF_2)) // expressions differ in spaces only (Floats) NaN : int TestFloat(float F) { if (F == F) // Identical float values used return 1; return 0; } int TestFloat(float F) { // Testing NaN. if (F != F && F == F) // does not warn return 1; return 0; } misc-static-assert cert-dcl03-c . assert() static_assert() . static_assert() . misc-throw-by-value-catch-by-reference cert-err09-cpp cert-err61-cpp . "Throw by value, catch by reference" "C++ Coding Standards" H. Sutter A. Alexandrescu ERR61-CPP CERT C++ Catch exceptions by lvalue reference . : o . (slicing) . o (char wchar_t ) . o (moved named values) . catch . o . . o (re-throw) . throw; . CheckThrowTemporaries ERR09-CPP CERT Throw anonymous temporaries . true . WarnOnLargeObject (trivial) . . MaxSize . false . MaxSize . WarnOnLargeObject true . std::numeric_limits::max() . size_t . misc-unconventional-assign-operator / return . o Class& . o lvalue (const) rvalue ( int) . o private (deleted) . o *this . misc-uniqueptr-reset-release unique_ptr::reset(release()) std::move() . : std::unique_ptr x, y; x.reset(y.release()); -> x = std::move(y); y rvalue std::move() . x y std::unique_ptr* . IncludeStyle include : llvm google. llvm . misc-unused-alias-decls (namespace alias) . namespace my_namespace { class C {}; } namespace unused_alias = ::my_namespace; misc-unused-parameters . ( ). (translation unit) . -Wunused-parameter . ( StrictMode <#cmdoption- arg-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`*/ } StrictMode false ( ) ( - ). . IgnoreVirtual (virtual) . true . false . misc-unused-using-decls using . using API . HeaderFileExtensions . : // main.cpp namespace n { class C; } using n::C; // Never actually used. misc-use-anonymous-namespace static (global scope) (anonymous namespace) . C++ << >> . static (deprecation) C [1]. static . static : o (antipattern) . HeaderFileExtensions . o const constexpr C++ (internal linkage) . : // Bad static void foo(); static int x; // Good namespace { void foo(); int x; } // namespace [1] Undeprecating static misc-use-internal-linkage static ( C++) (internal linkage) . . (dead code) . : int v1; // can be marked as static void fn1() {} // can be marked as static // already declared as extern extern int v2; void fn3(); // without function body in all declaration, maybe external linkage void fn3(); // === C++-specific === struct S1 {}; // can be moved into anonymous namespace namespace { // already in anonymous namespace int v2; void fn2(); struct S2 {}; } // export declarations export void fn4() {} export namespace t { void fn5() {} } export int v2; export class C {}; FixMode . UseStatic . o None . o UseStatic static . AnalyzeFunctions . true . AnalyzeVariables . true . AnalyzeTypes ( C++) (struct class union enum) . true . modernize-avoid-bind std::bind boost::bind (lambdas) . (value-capture) (reference capture) std::ref boost::ref . (callables) (member functions) (function objects) (free functions) . bind . (fix-it) placeholder . : int add(int x, int y) { return x + y; } : void f() { int x = 2; auto clj = std::bind(add, x, _1); } : void f() { int x = 2; auto clj = [=](auto && arg1) { return add(x, arg1); }; } std::bind (type information) (object files) . PermissiveParameterList true auto&&... (placeholder) . (fix-it) bind (type erased) std::function . false . : int add(int x, int y) { return x + y; } int foo() { std::function ignore_args = std::bind(add, 2, 2); return ignore_args(3, 3); } 4 . ignore_args . PermissiveParameterList : int add(int x, int y) { return x + y; } int foo() { std::function ignore_args = [] { return add(2, 2); } return ignore_args(3, 3); } operator() . (permissive parameter list) : int add(int x, int y) { return x + y; } int foo() { std::function ignore_args = [](auto&&...) { return add(2, 2); } return ignore_args(3, 3); } . C++14 . modernize-avoid-c-arrays cppcoreguidelines-avoid-c-arrays . hicpp-avoid-c-arrays . C std::array<> / std::vector<> . C . C std::span / gsl::span . (fix-it) . 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 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 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 extern "C" C C++ . // Some header extern "C" { int f[] = {1, 2}; // not diagnosed int j[1]; // not diagnosed inline void bar() { { int j[j[0]]; // not diagnosed } } } main() . char* argv[] char** argv std::array<> . AllowStringArrays true ( false ) (string literals) . . : const char name[] = "Some name"; modernize-avoid-c-style-cast C (C-style casts) . C (const_cast static_cast reinterpret_cast ). . -Wold-style-cast . -Wold-style-cast . class A { public: std::string v; }; A a; double *num = (double*)(&a); // Compiles! Hides danger // num = static_cast(&a); // Won't compile (good!) num = reinterpret_cast(&a); // Compiles, danger is explicit cpplint.py: readability/casting. modernize-avoid-setjmp-longjmp setjmp() longjmp() C++ . throw catch . CERT C++ : ERR52-CPP. Do not use setjmp() or longjmp() . modernize-avoid-variadic-functions ( ) (variadic) C . C (parameter pack) C++ . CERT C++ : DCL50-CPP. Do not define a C-style variadic function . modernize-concat-nested-namespaces namespace a { namespace b { ... } } C++17 : namespace a::b { ... }. (inline) . : 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(); } } : 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 C C++ C++ . C++ . [depr.c.headers] C++14 . C C++ . // C++ source file... #include #include // becomes #include // No 'stdbool.h' here. : C++ (global namespace) . . o o o o o // deprecated since C++11 o o o o o o o o o o o o o o // deprecated since C++11 o o // deprecated since C++11 o o C++11 C++11 -- . C++ : o o o include extern "C" { ... } (API) C C++ . // C++ source file... extern "C" { #include // Left intact. #include // Left intact. } CheckHeaderFile clang-tidy include C++ C include . (false-positive) (fixit- hints) . C++ true . false . modernize-deprecated-ios-base-aliases std::ios_base . +----------------------------+-------------------------+ | | | | | | +----------------------------+-------------------------+ |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 for(...; ...; ...) (range-based) C++11 . : o . o (iterators). o operator[] at(). MinConfidence risky ( enum ) (semantics) . risky 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 risky Range-based loops evaluate end() only once . reasonable () .end() .size() reasonable reasonable () . // using size() is considered reasonable for (int i = 0; i < container.size(); ++i) cout << container[i]; safe risky reasonable safe safe . int arr[] = {1,2,3}; for (int i = 0; i < 3; ++i) cout << arr[i]; : const int N = 5; int arr[] = {1,2,3,4,5}; vector 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::iterator it = v.begin(); it != v.end(); ++it) cout << *it; // reasonable conversion for (vector::iterator it = begin(v); it != end(v); ++it) cout << *it; // reasonable conversion for (vector::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]; reasonable (): const int N = 5; int arr[] = {1,2,3,4,5}; vector 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) rbegin rend (container) . C++20 ranges C++20 . UseCxx20ReverseRanges true C++20 std::views::reverse . true . MakeReverseRangeFunction rbegin rend begin end rbegin rend . std::views::reverse llvm::reverse . . MakeReverseRangeHeader MakeReverseRangeFunction . range/v3/view/reverse.hpp llvm/ADT/STLExtras.h . MakeReverseRangeFunction . include include . . IncludeStyle include : llvm google. llvm . (semantics) . . . for (int i = 0; i < N; /* This will be deleted */ ++i) { } end() for C++11 .end() . .end() . // 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) { } risky () . .end() . bool flag = false; for (vector::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; } . 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; } .end() (side effects) . .end() .end() . iterator end() { num_of_end_calls++; return container.end(); } operator->() operator->() (overload) . operator->() (implicit dereference) for . . operator->() . 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->() } (iterator) . risky risky . safe . vector vec; vector *ptr = &vec; vector &ref = vec; for (vector::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 for (range-based) OpenMP 5 OpenMP 5 . for OpenMP 5 . ( ) for OpenMP for OpenMP NOLINT ( Suppressing Undesired Diagnostics <#clang-tidy-nolint> ) for . modernize-macro-to-enum enum (unscoped anonymous enum) . enum (enumerator) . C++ Enum.1: Prefer enumerations over macros . : o (integral literal) . - + ~ ! , - + * / % & | ^ < > <= >= == != || && << >> <=> ?: GNU . . . sizeof . o (comment) . o . o . (include guard .) o . o . o . o (undefined) . o (top-level) . enum . enum (refactoring) enum (scoped enum) . . clang-tidy . : enum . C enum int . 1 << 40 int int . : #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. : 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. }; std::shared_ptr new std::make_shared . auto my_ptr = std::shared_ptr(new MyPair(1, 2)); // becomes auto my_ptr = std::make_shared(1, 2); std::shared_ptr::reset() new std::make_shared . my_ptr.reset(new MyPair(1, 2)); // becomes my_ptr = std::make_shared(1, 2); MakeSmartPtrFunction make-shared-ptr . std::make_shared . MakeSmartPtrFunctionHeader make-shared-ptr . . IncludeStyle include : llvm google. llvm . IgnoreMacros true . true . IgnoreDefaultInitialization false (default initialization) (value initialization) . true . modernize-make-unique std::unique_ptr new std::make_unique ( C++14) . auto my_ptr = std::unique_ptr(new MyPair(1, 2)); // becomes auto my_ptr = std::make_unique(1, 2); std::unique_ptr::reset() new std::make_unique . my_ptr.reset(new MyPair(1, 2)); // becomes my_ptr = std::make_unique(1, 2); MakeSmartPtrFunction make-unique-ptr . std::make_unique . MakeSmartPtrFunctionHeader make-unique-ptr . . IncludeStyle include : llvm google. llvm . IgnoreMacros true . true . IgnoreDefaultInitialization false (default initialization) (value initialization) . true . modernize-min-max-use-initializer-list std::min std::max (initializer list) . : int a = std::max(std::max(i, j), k); : int a = std::max({i, j, k}); initializer list (non-trivial) . std::ref std::cref : std::string b = std::max({std::ref(i), std::ref(j), std::ref(k)}); IncludeStyle (include-style) llvm google. llvm . IgnoreNonTrivialTypes . true . IgnoreTrivialTypesOfSizeAbove ( ) . 32 . modernize-pass-by-value (move semantics) (pass-by-value) (const-reference) . () . rvalue (move construction) . : 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 } : pass-by-value . ! Pass-by-value (const-references) . std::move() . std::move() include . include . #include 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); } . : #include void pass(const std::string &S); struct Foo { Foo(const std::string &S) : Str(S) { pass(S); } std::string Str; }; (init-list) "" . : 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" } (delayed template parsing) . : Clang Compiler User's Manual - Microsoft extensions . -fdelayed-template-parsing -fno-delayed-template-parsing . : template 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)) {} }; : (pass-by-value) : Want Speed? Pass by Value . IncludeStyle include llvm google. llvm . ValuesOnly true . false . modernize-raw-string-literal (raw string literals) . : 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]\\)"}; : 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]\))"}; : \\ \' \" \? (ASCII) . . . . form feed . form feed . DelimiterStem . : R"stem_delimiter(contents)stem_delimiter". lit . ReplaceShorterLiterals . true . false ( ). modernize-redundant-void-arg void. : +-----------------------+-------------------------+ | | | | | | | | | +-----------------------+-------------------------+ |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 std::auto_ptr std::unique_ptr ( C++11) . std::move() std::unique_ptr . : -void take_ownership_fn(std::auto_ptr int_ptr); +void take_ownership_fn(std::unique_ptr int_ptr); void f(int x) { - std::auto_ptr a(new int(x)); - std::auto_ptr b; + std::unique_ptr a(new int(x)); + std::unique_ptr b; - b = a; - take_ownership_fn(b); + b = std::move(a); + take_ownership_fn(std::move(b)); } std::move() include . include . o ( ) . o std::auto_ptr ( ) . std::unique_ptr std::unique_ptr std::auto_ptr . std::auto_ptr ( ). // <3rd-party header...> std::auto_ptr get_value(); const std::auto_ptr & get_ref(); // -std::auto_ptr a(get_value()); +std::unique_ptr a(get_value()); // ok, unique_ptr constructed from auto_ptr -const std::auto_ptr & p = get_ptr(); +const std::unique_ptr & p = get_ptr(); // won't compile o (Non-instantiated templates) . template void f() { std::auto_ptr p; } // only 'f()' (or similar) will trigger the replacement. IncludeStyle include : llvm google. llvm . modernize-replace-disallow-copy-and-assign-macro DISALLOW_COPY_AND_ASSIGN(Type) (deleted) . delete C++11 (private) . API . delete C++11 private (delete) . : class Foo { private: DISALLOW_COPY_AND_ASSIGN(Foo); }; : class Foo { private: Foo(const Foo &) = delete; const Foo &operator=(const Foo &) = delete; }; o private . modernize-use-equals-delete <> private . MacroName . DISALLOW_COPY_AND_ASSIGN . : modernize-replace-random-shuffle std::random_shuffle std::shuffle . C++17 std::random_shuffle . . std::vector v; // First example std::random_shuffle(vec.begin(), vec.end()); // Second example std::random_shuffle(vec.begin(), vec.end(), randomFunc); : std::shuffle(vec.begin(), vec.end(), std::mt19937(std::random_device()())); randomFunc randomFunc . std::random_device . . (seeding) : std::mt19937 . : std::shuffle(v.begin(), v.end(), []() { std::mt19937::result_type seeds[std::mt19937::state_size]; std::random_device device; std::uniform_int_distribution 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 return (braced initializer list) . return . Foo bar() { Baz baz; return Foo(baz); } // transforms to: Foo bar() { Baz baz; return {baz}; } modernize-shrink-to-fit (copy and swap) shrink_to_fit() . shrink_to_fit() . shrink_to_fit() C++11 . modernize-type-traits (type traits) traits<...>::type traits<...>::value traits_t<...> traits_v<...> . : std::is_integral::value std::is_same::value typename std::add_const::type std::make_signed::type : std::is_integral_v std::is_same_v std::add_const_t std::make_signed_t Options IgnoreMacros true (traits) . : (Fixes) . #define IS_SIGNED(T) std::is_signed::value false . Limitations ( std::chrono::is_clock std::chrono::treat_as_floating_point) . modernize-unary-static-assert static_assert (fix-it note) static_assert . C++17 . : void f_textless(int a) { static_assert(sizeof(a) <= 10, ""); } : void f_textless(int a) { static_assert(sizeof(a) <= 10); } modernize-use-auto auto . : std::vector::iterator I = my_container.begin(); // transforms to: auto I = my_container.begin(); auto . auto . : int val = 42; InfoStruct &I = SomeObject.getInfo(); // Should not become: auto val = 42; auto &I = SomeObject.getInfo(); auto . (self-documenting) . auto . (Iterators) . . for (std::vector::iterator I = my_container.begin(), E = my_container.end(); I != E; ++I) { } // for (auto I = my_container.begin(), E = my_container.end(); I != E; ++I) { } : o std : o array o deque o forward_list o list o vector o map o multimap o set o multiset o unordered_map o unordered_multimap o unordered_set o unordered_multiset o queue o priority_queue o stack o : o iterator o reverse_iterator o const_iterator o const_reverse_iterator o typedef . std::vector::iterator typedef . : // . std::vector::iterator I = MyVec.begin(); { using namespace std; list::iterator I = MyList.begin(); } // J auto typedef // . typedef std::map::const_iterator map_iterator; map_iterator J = MyMap.begin(); // // std::vector::iterator typedef . __gnu_cxx::__normal_iterator K = MyVec.begin(); o getUser (braced initializer list) . auto std::initializer_list . New new : new. auto . TypeName *my_pointer = new TypeName(my_param); // auto *my_pointer = new TypeName(my_param); : o ( ). o new . o new . TypeName *my_first_pointer = new TypeName, *my_second_pointer = new TypeName; // auto *my_first_pointer = new TypeName, *my_second_pointer = new TypeName; (Cast expressions) : . auto . TypeName *my_pointer = static_cast(my_param); // becomes auto *my_pointer = static_cast(my_param); static_cast dynamic_cast const_cast reinterpret_cast C ( llvm::dyn_cast boost::lexical_cast gsl::narrow_cast) . type . o (explicit conversion constructor) . o (User-defined iterators) . MinTypeNameLength ( 5 ) . . (long int) . RemoveStars ( ) true * . // MinTypeNameLength = 0, RemoveStars=0 int a = static_cast(foo()); // ---> auto a = ... // length(bool *) = 4 bool *b = new bool; // ---> auto *b = ... unsigned c = static_cast(foo()); // ---> auto c = ... // MinTypeNameLength = 5, RemoveStars=0 int a = static_cast(foo()); // ---> int a = ... bool b = static_cast(foo()); // ---> bool b = ... bool *pb = static_cast(foo()); // ---> bool *pb = ... unsigned c = static_cast(foo()); // ---> auto c = ... // length(long int) = 8 long int d = static_cast(foo()); // ---> auto d = ... // MinTypeNameLength = 5, RemoveStars=1 int a = static_cast(foo()); // ---> int a = ... // length(int * * ) = 5 int **pa = static_cast(foo()); // ---> auto pa = ... bool b = static_cast(foo()); // ---> bool b = ... bool *pb = static_cast(foo()); // ---> auto pb = ... unsigned c = static_cast(foo()); // ---> auto c = ... long int d = static_cast(foo()); // ---> auto d = ... RemoveStars true ( false ) auto typedef . . : 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 bool . bool p = 1; bool f = static_cast(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; IgnoreMacros true . true . modernize-use-constraints std::enable_if requires C++20. std::enable_if SFINAE (type traits) . enable_if (meta-arity) . C++20 (concepts) (constraints) . std::enable_if requires C++20 . . std::enable_if 1. std::enable_if 2. std::enable_if . boost::enable_if . std::enable_if . // enable_if in function return type template std::enable_if_t only_if_t_has_the_trait() { ... } // enable_if in the trailing template parameter template = 0> void another_version() { ... } template typename std::enable_if::type existing_constraint() requires (T::another_value) { return Obj{}; } template = 0> struct my_class {}; : // warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints] template 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 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 std::enable_if::type existing_constraint() requires (T::another_value) { return Obj{}; } // The tool will not emit a diagnostic or attempt to replace the code. template = 0> struct my_class {}; : . modernize-use-default modernize-use-equals-default <> . modernize-use-default-member-init C++11 . . '= 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}; }; : (built-in) (enums) . readability-redundant-member-init . UseAssignment true ( false ) . : struct A { A() {} A(int i) : i(i) {} int i = 5; double j = 10.0; }; IgnoreMacros true ( true ) . modernize-use-designated-initializers (aggregate types) (designated initializers) . struct . . C++20 . . : struct S { int i, j; }; S s{.i = 1, .j = 2}; S s{1, 2}; i j S . C++20 . C99/C++20 . C -Wc99-designator C++ -Wc++20-designator . IgnoreMacros false . true . IgnoreSingleElementAggregates false . true . std::array . RestrictToPODTypes true Plain Old Data (POD) . C++ . false . StrictCStandardCompliance false C99 . true . StrictCppStandardCompliance false C++20 . true . modernize-use-emplace STL push_back push push_front . emplace . insert . insert insert emplace . ContainersWithPushBack ContainersWithPush ContainersWithPushFront push_back push push_front . : o ContainersWithPushBack: std::vector std::deque std::list. o ContainersWithPush: std::stack std::queue std::priority_queue. o ContainersWithPushFront: std::forward_list std::list std::deque. emplace emplace_back . (move) (copy) . emplace STL try_emplace std::map std::unordered_map . EmplacyFunctions value_type emplace value_type . : std::vector v; v.push_back(MyClass(21, 37)); v.emplace_back(MyClass(21, 37)); std::vector> w; w.push_back(std::pair(21, 37)); w.push_back(std::make_pair(21L, 37L)); w.emplace_back(std::make_pair(21L, 37L)); : std::vector v; v.emplace_back(21, 37); v.emplace_back(21, 37); std::vector> w; w.emplace_back(21, 37); w.emplace_back(21L, 37L); w.emplace_back(21L, 37L); std::make_pair std::make_tuple push_back std::pair std::tuple . TupleTypes TupleMakeFunctions . . : std::vector > v; v.push_back("abc"); : std::vector > v; v.emplace_back("abc"); (exception safe) . push_back . std::vector> v; v.push_back(std::unique_ptr(new int(0))); auto *ptr = new int(1); v.push_back(std::unique_ptr(ptr)); emplace_back (emplacement) ( ) (leak) . <> <> . : std::unique_ptr std::shared_ptr std::auto_ptr. SmartPointers . : o (bit-field) ( rvalue/universal reference ) o new ( ) o (derived-to-base cast) . C++11 . ContainersWithPushBack (semicolon) push_back . ContainersWithPush push . ContainersWithPushFront push_front . IgnoreImplicitConstructors true push_back : std::vector v; v.push_back("a"); // Ignored when IgnoreImplicitConstructors is `true`. false . SmartPointers . TupleTypes std::tuple. TupleMakeFunctions std::make_tuple. push_back emplace_back . EmplacyFunctions emplace . : vector::emplace_back. . STL . std::vector> x; x.push_back(MakeMyTuple(1, false, 'x')); x.emplace_back(MakeMyTuple(1, false, 'x')); : std::vector> x; x.emplace_back(1, false, 'x'); x.emplace_back(1, false, 'x'); TupleTypes MyTuple TupleMakeFunctions MakeMyTuple EmplacyFunctions vector::emplace_back . modernize-use-equals-default = default; . (explicitly defaulted) (trivial) . struct A { A() {} ~A(); }; A::~A() {} // becomes struct A { A() = default; ~A(); }; A::~A() = default; : (Move-constructor) (move- assignment operator) . IgnoreMacros true . true . modernize-use-equals-delete = delete . private public . C++11 << >> private . ( ) ( ) . C++11 . = delete public . (false positives) (translation unit) . = delete public . // 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 true ( true ) . modernize-use-integer-sign-comparison C++20 std::cmp_* . C++20 . : unsigned int func(int a, unsigned int b) { return a == b; } #include unsigned int func(int a, unsigned int b) { return std::cmp_equal(a, b); } IncludeStyle include llvm google. llvm . EnableQtSupport q20::cmp_* C++17 Qt . false . modernize-use-nodiscard [[nodiscard]] ( C++17) . : o [[nodiscard]] [[noreturn]] __attribute__((warn_unused_result)) [[clang::warn_unused_result]] [[gcc::warn_unused_result]] o void o (non-template) o const o (non-variadic) o (non-const reference) o o (template parameters) o o mutable o (Lambdas) o (conversion functions) . . ( / I/O) . bool empty() const; bool empty(int i) const; : [[nodiscard]] bool empty() const; [[nodiscard]] bool empty(int i) const; ReplacementString [[nodiscard]] . C++17 . bool empty() const; bool empty(int i) const; : NO_DISCARD bool empty() const; NO_DISCARD bool empty(int i) const; ReplacementString NO_DISCARD . : ReplacementString C++ (scope) fix-it . : __attribute__ [[nodiscard]] C++17 . modernize-use-noexcept (dynamic exception specifications) noexcept ( C++11) . throw() noexcept throw([,...]) throw(...) noexcept(false) . void foo() throw(); void bar() throw(int) {} : void foo() noexcept; void bar() noexcept(false) {} ReplacementString ReplacementString <#cmdoption-arg-ReplacementString> noexcept . noexcept . Fix-it (non-throwing) . void bar() throw(int); void foo() throw(); : void bar() throw(int); // No fix-it generated. void foo() NOEXCEPT; ReplacementString <#cmdoption-arg- ReplacementString> NOEXCEPT . UseNoexceptFalse fix-it throw() (destructors) delete noexcept(true) . 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); } : void foo() {} struct bar { void foobar(); void operator delete(void *ptr) noexcept(false); void operator delete[](void *ptr) noexcept(false); ~bar() noexcept(false); } UseNoexceptFalse false . modernize-use-nullptr ( NULL 0) C++11 C23 nullptr . void assignment() { char *a = NULL; char *b = 0; char c = 0; } int *ret_ptr() { return 0; } : void assignment() { char *a = nullptr; char *b = nullptr; char c = 0; } int *ret_ptr() { return nullptr; } IgnoredTypes (semicolon) (regex) (implicit casts) . : std::_CmpUnspecifiedParam::;^std::__cmp_cat::__unspec. NullMacros NULL . NULL . #define MY_NULL (void*)0 void assignment() { void *p = MY_NULL; } : #define MY_NULL NULL void assignment() { int *p = nullptr; } NullMacros MY_NULL . modernize-use-override override ( C++11) virtual . virtual . C++ . C++11 override final . (override) . : o . o . IgnoreDestructors true (destructors) . false . IgnoreTemplateInstantiations true (virtual function overrides) (template instantiations) . false . AllowOverrideAndFinal true override final . / override gcc -Wsuggest-override/gcc -Werror=suggest-override. false . OverrideSpelling override . C++11 . FinalSpelling final . C++11 . : override . modernize-use-ranges (iterator) ranges . auto Iter1 = std::find(Items.begin(), Items.end(), 0); auto AreSame = std::equal(Items1.cbegin(), Items1.cend(), std::begin(Items2), std::end(Items2)); : auto Iter1 = std::ranges::find(Items, 0); auto AreSame = std::ranges::equal(Items1, Items2); std : std::adjacent_find std::all_of std::any_of std::binary_search std::copy_backward std::copy_if std::copy std::destroy std::equal_range std::equal std::fill std::find_end std::find_if_not std::find_if std::find std::for_each std::generate std::includes std::inplace_merge std::iota std::is_heap_until std::is_heap std::is_partitioned std::is_permutation std::is_sorted_until std::is_sorted std::lexicographical_compare std::lower_bound std::make_heap std::max_element std::merge std::min_element std::minmax_element std::mismatch std::move_backward std::move std::next_permutation std::none_of std::partial_sort_copy std::partition_copy std::partition_point std::partition std::pop_heap std::prev_permutation std::push_heap std::remove_copy_if std::remove_copy std::remove std::remove_if std::replace_if std::replace std::reverse_copy std::reverse std::rotate std::rotate_copy std::sample std::search std::set_difference std::set_intersection std::set_symmetric_difference std::set_union std::shift_left std::shift_right std::sort_heap std::sort std::stable_partition std::stable_sort std::transform std::uninitialized_copy std::uninitialized_default_construct std::uninitialized_fill std::uninitialized_move std::uninitialized_value_construct std::unique_copy std::unique std::upper_bound. : range vector C++23 (proxy iterators) . (Reverse Iteration) std::views::reverse . auto AreSame = std::equal(Items1.rbegin(), Items1.rend(), std::crbegin(Items2), std::crend(Items2)); : auto AreSame = std::ranges::equal(std::views::reverse(Items1), std::views::reverse(Items2)); IncludeStyle include llvm google. llvm . UseReversePipe true ( false ) (pipe) . std::find(Items.rbegin(), Items.rend(), 0); : std::ranges::find(Items | std::views::reverse, 0); modernize-use-scoped-lock std::lock_guard C++17 std::scoped_lock . (Fix-its) std::lock_guard std::lock_guard std::scoped_lock . std::lock_guard: std::mutex M; std::lock_guard L(M); : std::mutex M; std::scoped_lock L(M); std::lock_guard std::adopt_lock: std::mutex M; std::lock(M); std::lock_guard L(M, std::adopt_lock); : std::mutex M; std::lock(M); std::scoped_lock L(std::adopt_lock, M); std::lock_guard : std::mutex M1, M2; std::lock(M1, M2); std::lock_guard Lock1(M1, std::adopt_lock); // warning: use single 'std::scoped_lock' instead of multiple 'std::lock_guard' std::lock_guard Lock2(M2, std::adopt_lock); // note: additional 'std::lock_guard' declared here std::lock_guard template : template