'\" t
.\" Man page generated from reStructuredText
.\" by the Docutils 0.23 manpage writer.
.
.
.nr rst2man-indent-level 0
.
.de1 rstReportMargin
\\$1 \\n[an-margin]
level \\n[rst2man-indent-level]
level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
-
\\n[rst2man-indent0]
\\n[rst2man-indent1]
\\n[rst2man-indent2]
..
.de1 INDENT
.\" .rstReportMargin pre:
. RS \\$1
. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
. nr rst2man-indent-level +1
.\" .rstReportMargin post:
..
.de UNINDENT
. RE
.\" indent \\n[an-margin]
.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
.nr rst2man-indent-level -1
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.TH "EXTRACLANGTOOLS" "1" "Jun 21, 2026" "22" "Extra Clang Tools"
.SH NAME
extraclangtools \- Extra Clang Tools Documentation
.sp
Welcome to the clang\-tools\-extra project which contains extra tools built using
Clang\(aqs tooling APIs.
.SH EXTRA CLANG TOOLS 22.1.8 RELEASE NOTES
.INDENT 0.0
.IP \(bu 2
Introduction
.IP \(bu 2
What\(aqs New in Extra Clang Tools 22.1.8?
.INDENT 2.0
.IP \(bu 2
Major New Features
.IP \(bu 2
Potentially Breaking Changes
.IP \(bu 2
Improvements to clangd
.INDENT 2.0
.IP \(bu 2
Compile flags
.IP \(bu 2
Diagnostics
.IP \(bu 2
Hover
.IP \(bu 2
Cross\-references
.IP \(bu 2
Inlay hints
.IP \(bu 2
Call hierarchy
.IP \(bu 2
Document symbols
.IP \(bu 2
Code folding
.IP \(bu 2
Code completion
.IP \(bu 2
Code actions
.IP \(bu 2
C++20 Modules support
.IP \(bu 2
Miscellaneous
.UNINDENT
.IP \(bu 2
Improvements to clang\-doc
.IP \(bu 2
Improvements to clang\-query
.IP \(bu 2
Improvements to clang\-tidy
.INDENT 2.0
.IP \(bu 2
New checks
.IP \(bu 2
New check aliases
.IP \(bu 2
Changes in existing checks
.IP \(bu 2
Removed checks
.IP \(bu 2
Miscellaneous
.UNINDENT
.IP \(bu 2
Improvements to include\-fixer
.IP \(bu 2
Improvements to clang\-include\-fixer
.IP \(bu 2
Improvements to modularize
.IP \(bu 2
Improvements to pp\-trace
.IP \(bu 2
Clang\-tidy Visual Studio plugin
.UNINDENT
.UNINDENT
.sp
Written by the LLVM Team \%
.SS Introduction
.sp
This document contains the release notes for the Extra Clang Tools, part of the
Clang release 22.1.8\&. Here we describe the status of the Extra Clang Tools in
some detail, including major improvements from the previous release and new
feature work. All LLVM releases may be downloaded from the LLVM releases web
site \%\&.
.sp
For more information about Clang or LLVM, including information about
the latest release, please see the Clang Web Site \% or
the LLVM Web Site \%\&.
.sp
Note that if you are reading this file from a Git checkout or the
main Clang web page, this document applies to the \fInext\fP release, not
the current one. To see the release notes for a specific release, please
see the releases page \%\&.
.SS What\(aqs New in Extra Clang Tools 22.1.8?
.sp
Some of the major new features and improvements to Extra Clang Tools are listed
here. Generic improvements to Extra Clang Tools as a whole or to its underlying
infrastructure are described first, followed by tool\-specific sections.
.SS Major New Features
.SS Potentially Breaking Changes
.INDENT 0.0
.IP \(bu 2
Deprecated the \fBclang\-tidy\fP \fBhicpp\fP module. All checks have been
moved to other modules instead. The \fBhicpp\fP module will be removed
for the 23.x release.
.IP \(bu 2
Deprecated the \fBclang\-tidy\fP \fBzircon\fP module. All checks have been
moved to the \fBfuchsia\fP module instead. The \fBzircon\fP module will be removed
in the 24th release.
.IP \(bu 2
Removed \fBclang\-tidy\fP\(aqs global options \fIIgnoreMacros\fP and
\fIStrictMode\fP, which were documented as deprecated since
\fBclang\-tidy\-20\fP\&. Users should use the check\-specific options of the
same name instead.
.IP \(bu 2
Removed \fIclang\-analyzer\-*\fP checks from default checks in \fBclang\-tidy\fP\&.
From now on, users should specify explicitly that they want CSA checks to run
in \fBclang\-tidy\fP via \fIclang\-analyzer\-*\fP\&.
.IP \(bu 2
Renamed a few \fBclang\-tidy\fP check options, as they
were misspelled:
.INDENT 2.0
.IP \(bu 2
\fINamePrefixSuffixSilenceDissimilarityTreshold\fP to
\fINamePrefixSuffixSilenceDissimilarityThreshold\fP in
bugprone\-easily\-swappable\-parameters \%<>
.IP \(bu 2
\fICharTypdefsToIgnore\fP to \fICharTypedefsToIgnore\fP in
bugprone\-signed\-char\-misuse \%<>
.UNINDENT
.IP \(bu 2
Modified the custom message format of bugprone\-unsafe\-functions \%<> by assigning a special meaning
to the character \fB>\fP at the start of the value of the option
\fBCustomFunctions\fP\&. If the option value starts with \fB>\fP, then the
replacement suggestion part of the message (which would be included by
default) is omitted. (This does not change the warning locations.)
.IP \(bu 2
\fBclang\-tidy\fP now displays warnings from all non\-system headers by
default. Previously, users had to explicitly opt\-in to header warnings using
\fI\-header\-filter=\(aq.*\(aq\fP\&. To disable warnings from non\-system, set \fI\-header\-filter\fP
to an empty string.
.IP \(bu 2
The \fBclang\-tidy/ClangTidyModuleRegistry.h\fP header has been deprecated and will
be removed in LLVM 24. All of the symbols it used to define have been moved into
\fBclang\-tidy/ClangTidyModule.h\fP\&.
.UNINDENT
.SS Improvements to clangd
.SS Compile flags
.INDENT 0.0
.IP \(bu 2
Added proper support for the \fB\-std=c++latest\fP flag, often used by
Windows users writing C++23 code.
.UNINDENT
.SS Diagnostics
.INDENT 0.0
.IP \(bu 2
Fixed a bug that caused the quick\-fix for the \fBreadability\-identifier\-naming\fP
diagnostic not to work in some editors.
.UNINDENT
.SS Hover
.INDENT 0.0
.IP \(bu 2
Added support for parsing and presenting doxygen and markdown documentation
.IP \(bu 2
Added a \fBMacroContentsLimit\fP config option to allow users to opt into
showing macro definitions in hovers even if they\(aqre very long
.IP \(bu 2
Fixed a bug that prevented documentation from being shown for members of
class templates defined in a header
.IP \(bu 2
Fixed a bug that prevented documentation from being shown for
abbreviated function templates
.UNINDENT
.SS Cross\-references
.INDENT 0.0
.IP \(bu 2
Improved \(dqgo to definition\(dq support for dependent \fBauto\fP
.IP \(bu 2
Improved \(dqgo to definition\(dq support for C++23 \(dqdeducing this\(dq
.IP \(bu 2
Fixed a bug where attributes on a method broke various features including
\(dqgo to definition\(dq on a method\(aqs name
.IP \(bu 2
\(dqFind references\(dq on a constructor now finds call sites of forwarding
functions such as \fBmake_unique\fP as well
.IP \(bu 2
\(dqDocument links\(dq now supports \fB#include\fP directives with a macro argument
.UNINDENT
.SS Inlay hints
.INDENT 0.0
.IP \(bu 2
Show designator hints for aggregate initialization of structures
with parentheses\-list initialization (\fBCXXParenListInitExpr\fP) syntax.
.IP \(bu 2
Show type hints for simple cases of dependent \fBauto\fP
.UNINDENT
.SS Call hierarchy
.INDENT 0.0
.IP \(bu 2
Support invoking call hierarchy on enum constants
.IP \(bu 2
When invoked on a virtual function, show callers of base functions as well
.UNINDENT
.SS Document symbols
.INDENT 0.0
.IP \(bu 2
Include inline friend functions in document symbols
.UNINDENT
.SS Code folding
.INDENT 0.0
.IP \(bu 2
Support folding of preprocessor branches
.IP \(bu 2
Support folding of \fB#pragma region\fP blocks
.UNINDENT
.SS Code completion
.INDENT 0.0
.IP \(bu 2
Added a new \fBMacroFilter\fP configuration option to \fBCompletion\fP to
allow fuzzy\-matching with the \fBFuzzyMatch\fP option when suggesting
macros. \fBExactPrefix\fP is the default, which retains previous
behavior of suggesting macros which match the prefix exactly.
.IP \(bu 2
Improved support for C++23 \(dqdeducing this\(dq
.IP \(bu 2
Header insertion now checks \fBAngledHeaders\fP and \fBQuotedHeaders\fP
against resolved rather than spelled paths, consistent with the
existing behaviour of include\-cleaner diagnostics.
.UNINDENT
.SS Code actions
.INDENT 0.0
.IP \(bu 2
New \fBOverride pure virtual methods\fP code action. When invoked on a class
definition, this action automatically generates C++ \fBoverride\fP declarations
for all pure virtual methods inherited from its base classes that have not yet
been implemented. The generated method stubs prompts the user for the actual
implementation. The overrides are intelligently grouped under their original
access specifiers (e.g., \fBpublic\fP, \fBprotected\fP), creating new access
specifier blocks if necessary.
.IP \(bu 2
Improved the \(dqmove function body out\-of\-line\(dq code action\(aqs logic for choosing
where to place the definition. It now tries to place it next to the definition
of a method with an adjacent declaration.
.UNINDENT
.SS C++20 Modules support
.INDENT 0.0
.IP \(bu 2
Fixed a crash when using \fB\-\-experimental\-modules\-support\fP without a
compilation database
.IP \(bu 2
Added a \fB\-\-debug\-modules\-builder\fP option to help debug clangd\(aqs modules support
.IP \(bu 2
Improved diagnostics related to modules
.IP \(bu 2
Clangd now tries to reuse a module from the project\(aqs build if it\(aqs suitable
.UNINDENT
.SS Miscellaneous
.INDENT 0.0
.IP \(bu 2
Add wildcard \fB\&.gitignore\fP file to the clangd index directory.
.UNINDENT
.SS Improvements to clang\-doc
.INDENT 0.0
.IP \(bu 2
Use the Mustache HTML generator as the default HTML option.
.IP \(bu 2
Document concepts, typedefs, aliases, public class members, nested records,
nested namespaces, global functions, global variables, protected methods and
members and friends in HTML.
.IP \(bu 2
Document \fBthrows\fP comments in HTML.
.IP \(bu 2
Add definition location for classes in HTML.
.IP \(bu 2
Show class template declaration in HTML.
.IP \(bu 2
Add a top\-level index page in HTML. This page lists the top\-level namespaces
and serves as the documentation\(aqs root URL.
.IP \(bu 2
Add a \fBHome\fP button to the navigation bar which replaces non\-useful buttons.
This new button links to the top\-level index page.
.IP \(bu 2
Add a breadcrumb navigation bar to the navbar. This helps navigate through a
documented entity\(aqs context.
.IP \(bu 2
If a filename is too long, then the name will be truncated and the documented
entity\(aqs USR will be concatenated to guarantee its uniqueness.
.IP \(bu 2
Revert the flat directory structure to a nested directory structure.
.UNINDENT
.SS Improvements to clang\-query
.INDENT 0.0
.IP \(bu 2
Matcher queries interpreted by clang\-query are now support trailing comma (,)
in matcher arguments. Note that C++ still doesn\(aqt allow this in function
arguments. So when porting a query to C++, remove all instances of trailing
comma (otherwise C++ compiler will just complain about \(dqexpected expression\(dq).
.UNINDENT
.SS Improvements to clang\-tidy
.INDENT 0.0
.IP \(bu 2
The \fBcheck_clang_tidy.py\fP tool now recognizes the \fB\-std\fP argument
when run over C files. If \fB\-std\fP is not specified, it defaults to
\fBc99\-or\-later\fP\&.
.IP \(bu 2
\fBclang\-tidy\fP now displays warnings from all non\-system headers by
default. Previously, users had to explicitly opt\-in to header warnings using
\fI\-header\-filter=\(aq.*\(aq\fP\&. To disable warnings from non\-system, set \fI\-header\-filter\fP
to an empty string.
.IP \(bu 2
\fBclang\-tidy\fP no longer attempts to analyze code from system headers
by default, greatly improving performance. This behavior is disabled if the
\fISystemHeaders\fP option is enabled.
.IP \(bu 2
\fBclang\-tidy\fP now supports query based custom checks by \fICustomChecks\fP
configuration option.
Query Based Custom Check Document \%<>
.IP \(bu 2
The \fBrun\-clang\-tidy.py\fP and \fBclang\-tidy\-diff.py\fP scripts
now run checks in parallel by default using all available hardware threads.
Both scripts display the number of threads being used in their output.
.IP \(bu 2
Improved \fBrun\-clang\-tidy.py\fP by adding a new option
\fIenable\-check\-profile\fP to enable per\-check timing profiles and print a
report based on all analyzed files.
.IP \(bu 2
Improved documentation of the \fI\-line\-filter\fP command\-line flag of
\fBclang\-tidy\fP and \fBrun\-clang\-tidy.py\fP\&.
.IP \(bu 2
Improved \fBclang\-tidy\fP option \fI\-quiet\fP by suppressing diagnostic
count messages.
.IP \(bu 2
Improved \fBclang\-tidy\fP by not crashing when an empty \fIdirectory\fP
field is used in a compilation database; the current working directory
will be used instead, and an error message will be printed.
.IP \(bu 2
Removed \fBclang\-tidy\fP\(aqs global options \fIIgnoreMacros\fP and
\fIStrictMode\fP, which were documented as deprecated since
\fBclang\-tidy\-20\fP\&. Users should use the check\-specific options of the
same name instead.
.IP \(bu 2
Improved \fBrun\-clang\-tidy.py\fP and \fBclang\-tidy\-diff.py\fP
scripts by adding the \fI\-hide\-progress\fP option to suppress progress and
informational messages.
.IP \(bu 2
Removed \fIclang\-analyzer\-*\fP check from default checks in \fBclang\-tidy\fP\&.
From now on, users should specify explicitly that they want CSA checks to run
in \fBclang\-tidy\fP\&.
.IP \(bu 2
Improved \fBclang\-tidy\fP by adding the \fI\-\-removed\-arg\fP option to remove
arguments sent to the compiler when invoking Clang\-Tidy. This option was also
added to \fBrun\-clang\-tidy.py\fP and \fBclang\-tidy\-diff.py\fP and
can be configured in the config file through the \fIRemovedArgs\fP option.
.IP \(bu 2
Deprecated the \fBclang\-tidy\fP \fBzircon\fP module. All checks have been
moved to the \fBfuchsia\fP module instead. The \fBzircon\fP module will be removed
in the 24th release.
.IP \(bu 2
Improved \fBclang\-tidy\fP configuration parsing by allowing the same list
syntax in \fIWarningsAsErrors\fP as in \fIChecks\fP\&.
.UNINDENT
.SS New checks
.INDENT 0.0
.IP \(bu 2
New abseil\-unchecked\-statusor\-access \%<> check.
.sp
Finds uses of \fBabsl::StatusOr\fP without checking if a value is present.
.IP \(bu 2
New bugprone\-derived\-method\-shadowing\-base\-method \%<> check.
.sp
Finds derived class methods that shadow a (non\-virtual) base class method.
.IP \(bu 2
New bugprone\-invalid\-enum\-default\-initialization \%<> check.
.sp
Detects default initialization (to 0) of variables with \fBenum\fP type where
the enum has no enumerator with value of 0.
.IP \(bu 2
New cppcoreguidelines\-pro\-bounds\-avoid\-unchecked\-container\-access \%<>
check.
.sp
Finds calls to \fBoperator[]\fP in STL containers and suggests replacing them
with safe alternatives.
.IP \(bu 2
New google\-runtime\-float \%<> check.
.sp
Finds uses of \fBlong double\fP and suggests against their use due to lack of
portability.
.IP \(bu 2
New llvm\-mlir\-op\-builder \%<> check.
.sp
Checks for uses of MLIR\(aqs old/to be deprecated \fBOpBuilder::create\fP form
and suggests using \fBT::create\fP instead.
.IP \(bu 2
New llvm\-use\-ranges \%<> check.
.sp
Finds calls to STL library iterator algorithms that could be replaced with
LLVM range\-based algorithms from \fBllvm/ADT/STLExtras.h\fP\&.
.IP \(bu 2
New misc\-override\-with\-different\-visibility \%<> check.
.sp
Finds virtual function overrides with different visibility than the function
in the base class.
.IP \(bu 2
New readability\-inconsistent\-ifelse\-braces \%<> check.
.sp
Detects \fBif\fP/\fBelse\fP statements where one branch uses braces and the other
does not.
.IP \(bu 2
New readability\-redundant\-parentheses \%<> check.
.sp
Detect redundant parentheses.
.IP \(bu 2
New readability\-redundant\-typename \%<> check.
.sp
Finds redundant uses of the \fBtypename\fP keyword.
.UNINDENT
.SS New check aliases
.INDENT 0.0
.IP \(bu 2
Renamed cert\-dcl50\-cpp \%<> to
modernize\-avoid\-variadic\-functions \%<>
keeping initial check as an alias to the new one.
.IP \(bu 2
Renamed cert\-dcl58\-cpp \%<> to
bugprone\-std\-namespace\-modification \%<>
keeping initial check as an alias to the new one.
.IP \(bu 2
Renamed cert\-env33\-c \%<> to
bugprone\-command\-processor \%<>
keeping initial check as an alias to the new one.
.IP \(bu 2
Renamed cert\-err34\-c \%<> to
bugprone\-unchecked\-string\-to\-number\-conversion \%<>
keeping initial check as an alias to the new one.
.IP \(bu 2
Renamed cert\-err52\-cpp \%<> to
modernize\-avoid\-setjmp\-longjmp \%<>
keeping initial check as an alias to the new one.
.IP \(bu 2
Renamed cert\-err58\-cpp \%<> to
bugprone\-throwing\-static\-initialization \%<>
keeping initial check as an alias to the new one.
.IP \(bu 2
Renamed cert\-err60\-cpp \%<> to
bugprone\-exception\-copy\-constructor\-throws \%<>
.IP \(bu 2
Renamed cert\-flp30\-c \%<> to
bugprone\-float\-loop\-counter \%<>
keeping initial check as an alias to the new one.
.IP \(bu 2
Renamed cert\-mem57\-cpp \%<> to
bugprone\-default\-operator\-new\-on\-overaligned\-type \%<>
keeping initial check as an alias to the new one.
.IP \(bu 2
Renamed cert\-msc30\-c \%<> to
misc\-predictable\-rand \%<>
keeping initial check as an alias to the new one.
.IP \(bu 2
Renamed cert\-msc32\-c \%<> to
bugprone\-random\-generator\-seed \%<>
keeping initial check as an alias to the new one.
.IP \(bu 2
Renamed cert\-msc50\-cpp \%<> to
misc\-predictable\-rand \%<>
keeping initial check as an alias to the new one.
.IP \(bu 2
Renamed cert\-msc51\-cpp \%<> to
bugprone\-random\-generator\-seed \%<>
keeping initial check as an alias to the new one.
.IP \(bu 2
Renamed cert\-oop57\-cpp \%<> to
bugprone\-raw\-memory\-call\-on\-non\-trivial\-type \%<>
keeping initial check as an alias to the new one.
.IP \(bu 2
Renamed cert\-oop58\-cpp \%<> to
bugprone\-copy\-constructor\-mutates\-argument \%<>
keeping initial check as an alias to the new one.
.IP \(bu 2
Renamed fuchsia\-multiple\-inheritance \%<> to
misc\-multiple\-inheritance \%<>
keeping initial check as an alias to the new one.
.IP \(bu 2
Renamed google\-build\-namespaces \%<> to
misc\-anonymous\-namespace\-in\-header \%<>
keeping initial check as an alias to the new one.
.IP \(bu 2
Renamed google\-readability\-casting \%<> to
modernize\-avoid\-c\-style\-cast \%<>
keeping initial check as an alias to the new one.
.UNINDENT
.SS Changes in existing checks
.INDENT 0.0
.IP \(bu 2
Improved bugprone\-chained\-comparison \%<> check by adding a
new option \fIIgnoreMacros\fP to suppress warnings within macro
expansions.
.IP \(bu 2
Improved bugprone\-dynamic\-static\-initializers \%<> check:
.INDENT 2.0
.IP \(bu 2
Avoided false positives for \fBconstexpr\fP variables whose initializers
are value\-dependent.
.IP \(bu 2
Added support for C++20 \fBconstinit\fP variables.
.UNINDENT
.IP \(bu 2
Improved bugprone\-easily\-swappable\-parameters \%<> check by
correcting a spelling mistake on its option
\fBNamePrefixSuffixSilenceDissimilarityTreshold\fP\&.
.IP \(bu 2
Improved bugprone\-exception\-escape \%<> check:
.INDENT 2.0
.IP \(bu 2
Exceptions from lambda captures are now diagnosed, exceptions in the
bodies of lambdas that aren\(aqt actually invoked are not.
.IP \(bu 2
Fixed an issue where the check wouldn\(aqt diagnose throws in arguments to
functions or constructors.
.IP \(bu 2
Added fine\-grained configuration via options \fICheckDestructors\fP,
\fICheckMoveMemberFunctions\fP, \fICheckMain\fP, \fICheckedSwapFunctions\fP, and
\fICheckNothrowFunctions\fP\&.
.UNINDENT
.IP \(bu 2
Improved bugprone\-infinite\-loop \%<> check by adding detection for
variables introduced by structured bindings.
.IP \(bu 2
Improved bugprone\-invalid\-enum\-default\-initialization \%<> with new
\fIIgnoredEnums\fP option to ignore specified enums during analysis.
.IP \(bu 2
Improved bugprone\-macro\-parentheses \%<> check by fixing false
positives when using C++ template parameters.
.IP \(bu 2
Improved bugprone\-narrowing\-conversions \%<> check by fixing
false positive from analysis of a conditional expression in C.
.IP \(bu 2
Improved bugprone\-not\-null\-terminated\-result \%<> check by fixing
bogus fix\-its for \fBstrncmp\fP and \fBwcsncmp\fP on Windows and
a crash caused by certain value\-dependent expressions.
.IP \(bu 2
Improved bugprone\-reserved\-identifier \%<> check by ignoring
declarations and macros in system headers.
.IP \(bu 2
Improved bugprone\-signed\-char\-misuse \%<> check by fixing
false positives on C23 enums with the fixed underlying type of signed char.
.IP \(bu 2
Improved bugprone\-sizeof\-expression \%<> check by fixing
a crash on \fBsizeof\fP of an array of dependent type.
.IP \(bu 2
Improved bugprone\-suspicious\-include \%<> check by adding
\fIIgnoredRegex\fP option.
.IP \(bu 2
Improved bugprone\-tagged\-union\-member\-count \%<> by fixing a false
positive when enums or unions from system header files or the \fBstd\fP
namespace are treated as the tag or the data part of a user\-defined
tagged union respectively.
.IP \(bu 2
Improved bugprone\-throw\-keyword\-missing \%<> check:
.INDENT 2.0
.IP \(bu 2
Now it only considers the canonical types of base classes as written.
.IP \(bu 2
Added a note on the base class that triggered the warning.
.IP \(bu 2
Fixed an issue where the check wouldn\(aqt fire in constructors or
(in certain contexts) lambdas.
.UNINDENT
.IP \(bu 2
Improved bugprone\-unchecked\-optional\-access \%<> check:
.INDENT 2.0
.IP \(bu 2
Added support for \fBNullableValue::makeValue\fP and
\fBNullableValue::makeValueInplace\fP to prevent false\-positives for
\fBBloombergLP::bdlb::NullableValue\fP\&.
.IP \(bu 2
Fixed false\-positives for \fBbsl::optional\fP containing allocator\-aware type.
.IP \(bu 2
Added the \fIIgnoreValueCalls\fP option to suppress diagnostics for
\fBoptional::value()\fP\&.
.IP \(bu 2
Added the \fIIgnoreSmartPointerDereference\fP option to ignore optionals
reached via smart\-pointer\-like dereference, while still diagnosing UB\-prone
dereferences via \fBoperator*\fP and \fBoperator\->\fP\&.
.UNINDENT
.IP \(bu 2
Improved bugprone\-unhandled\-self\-assignment \%<> check by adding
an additional matcher that generalizes the copy\-and\-swap idiom pattern
detection.
.IP \(bu 2
Improved bugprone\-unsafe\-functions \%<> check by hiding the default
suffix when the reason starts with the character \fI>\fP in the \fICustomFunctions\fP
option.
.IP \(bu 2
Improved bugprone\-use\-after\-move \%<> check:
.INDENT 2.0
.IP \(bu 2
Added \fIInvalidationFunctions\fP option to support custom invalidation functions.
.IP \(bu 2
Added \fIReinitializationFunctions\fP option to support custom reinitialization
functions.
.UNINDENT
.IP \(bu 2
Improved cppcoreguidelines\-avoid\-non\-const\-global\-variables \%<> check
by adding a new option \fIAllowThreadLocal\fP that suppresses warnings on
non\-const global variables with thread\-local storage duration.
.IP \(bu 2
Improved cppcoreguidelines\-init\-variables \%<> check by fixing the
insertion location for function pointers with multiple parameters.
.IP \(bu 2
Improved cppcoreguidelines\-macro\-usage \%<> check by excluding macro
bodies that starts with \fB__attribute__((..))\fP keyword.
Such a macro body is unlikely a proper expression and so suggesting users
an impossible rewrite into a template function should be avoided.
.IP \(bu 2
Improved cppcoreguidelines\-prefer\-member\-initializer \%<> check to
avoid false positives on inherited members in class templates.
.IP \(bu 2
Improved cppcoreguidelines\-pro\-bounds\-pointer\-arithmetic \%<> check
adding \fIAllowIncrementDecrementOperators\fP option to allow pointer arithmetic
via prefix/postfix increment or decrement operators.
.IP \(bu 2
Improved cppcoreguidelines\-pro\-type\-member\-init \%<> check to
correctly ignore \fBstd::array\fP and other array\-like containers when
\fIIgnoreArrays\fP option is set to \fItrue\fP\&.
.IP \(bu 2
Improved fuchsia\-multiple\-inheritance \%<>
by fixing an issue where the check would only analyze the first class with
a given name in the program, missing any subsequent classes with that same
name (declared in a different scope).
.IP \(bu 2
Improved google\-readability\-casting \%<> check by adding fix\-it
notes for downcasts and casts to void pointer.
.IP \(bu 2
Improved google\-readability\-todo \%<> check to accept the new TODO
format from the Google Style Guide.
.IP \(bu 2
Improved llvm\-prefer\-isa\-or\-dyn\-cast\-in\-conditionals \%<> check:
.INDENT 2.0
.IP \(bu 2
Fix\-it handles callees with nested\-name\-specifier correctly.
.IP \(bu 2
\fBif\fP statements with init\-statement (\fBif (auto X = ...; ...)\fP) are
handled correctly.
.IP \(bu 2
\fBfor\fP loops are supported.
.UNINDENT
.IP \(bu 2
Improved misc\-const\-correctness \%<> check:
.INDENT 2.0
.IP \(bu 2
Fixed false positives when pointers is transferred to non\-const references.
.IP \(bu 2
Fixed false positives of function pointer, on return of non\-const pointer,
on pointer\-to\-member operator.
.IP \(bu 2
Fixed false positives when the address of a variable is taken to be passed
to a function.
.UNINDENT
.IP \(bu 2
Improved misc\-coroutine\-hostile\-raii \%<> check by adding the option
\fIAllowedCallees\fP, that allows exempting safely awaitable callees from the
check.
.IP \(bu 2
Improved misc\-header\-include\-cycle \%<> check performance.
.IP \(bu 2
Improved misc\-use\-internal\-linkage \%<> check:
.INDENT 2.0
.IP \(bu 2
Added suggestion of internal linkage for user\-defined types (structs,
classes, unions, and enums).
.IP \(bu 2
Added fine\-grained options \fIAnalyzeFunctions\fP, \fIAnalyzeVariables\fP,
\fIAnalyzeTypes\fP to control whether the check should diagnose functions,
variables, and/or user\-defined types.
.IP \(bu 2
Enabled the check for C.
.UNINDENT
.IP \(bu 2
Improved modernize\-avoid\-c\-arrays \%<> to not diagnose array types
which are part of an implicit instantiation of a template.
.IP \(bu 2
Improved modernize\-use\-constraints \%<> check by fixing a crash on
uses of non\-standard \fBenable_if\fP with a signature different from
\fBstd::enable_if\fP (such as \fBboost::enable_if\fP).
.IP \(bu 2
Improved modernize\-use\-default\-member\-init \%<> check to
enhance the robustness of the member initializer detection.
.IP \(bu 2
Improved modernize\-use\-designated\-initializers \%<> check to
suggest using designated initializers for aliased aggregate types.
.IP \(bu 2
Improved modernize\-use\-integer\-sign\-comparison \%<> by providing
correct fix\-its when the right\-hand side of a comparison contains a
non\-C\-style cast.
.IP \(bu 2
Improved modernize\-use\-nullptr \%<> check by fixing a crash
on Windows when the check was enabled with a 32\-bit \fBclang\-tidy\fP
binary.
.IP \(bu 2
Improved modernize\-use\-override \%<> by fixing an issue where
the check would sometimes suggest inserting \fBoverride\fP in an invalid
place.
.IP \(bu 2
Improved modernize\-use\-ranges \%<> check to suggest using
the more idiomatic \fBstd::views::reverse\fP where it used to suggest
\fBstd::ranges::reverse_view\fP\&.
.IP \(bu 2
Improved modernize\-use\-scoped\-lock \%<> check by fixing a crash
on malformed code (common when using \fBclang\-tidy\fP through
\fBclangd\fP).
.IP \(bu 2
Improved modernize\-use\-std\-format \%<> check to correctly match
when the format string is converted to a different type by an implicit
constructor call.
.IP \(bu 2
Improved modernize\-use\-std\-print \%<> check to correctly match
when the format string is converted to a different type by an implicit
constructor call, and fixed a crash when handling format strings
containing non\-ASCII characters.
.IP \(bu 2
Improved modernize\-use\-using \%<> check to correctly provide fix\-its
for typedefs of pointers or references to array types.
.IP \(bu 2
Improved performance\-move\-const\-arg \%<> check by avoiding false
positives on trivially copyable types with a non\-public copy constructor.
.IP \(bu 2
Improved performance\-unnecessary\-copy\-initialization \%<> by printing
the type of the diagnosed variable.
.IP \(bu 2
Improved performance\-unnecessary\-value\-param \%<> by printing
the type of the diagnosed variable and correctly generating fix\-it hints for
parameter\-pack arguments.
.IP \(bu 2
Improved portability\-template\-virtual\-member\-function \%<> check to
avoid false positives on pure virtual member functions.
.IP \(bu 2
Improved readability\-container\-contains \%<> to support string
comparisons to \fBnpos\fP\&. Internal changes may cause new rare false positives
in non\-standard containers.
.IP \(bu 2
Improved readability\-container\-data\-pointer \%<> check by correctly
adding parentheses when the container expression is a dereference.
.IP \(bu 2
Improved readability\-container\-size\-empty \%<> check by correctly
generating fix\-it hints when size method is called from implicit \fBthis\fP,
ignoring default constructors with user provided arguments and adding
detection in container\(aqs method except \fBempty\fP\&.
.IP \(bu 2
Improved readability\-duplicate\-include \%<> check by adding
the \fBIgnoredFilesList\fP option (semicolon\-separated list of regexes or
filenames) to allow intentional duplicates.
.IP \(bu 2
Improved readability\-identifier\-naming \%<> check:
.INDENT 2.0
.IP \(bu 2
Now ignores declarations and macros in system headers.
.IP \(bu 2
The documentation is improved to differentiate the general options from the
specific ones.
.IP \(bu 2
Options for fine\-grained control over \fBconstexpr\fP variables were added.
.IP \(bu 2
Added default options which simplify configs by removing the need to specify
each identifier kind separately.
.UNINDENT
.IP \(bu 2
Improved readability\-implicit\-bool\-conversion \%<> check:
.INDENT 2.0
.IP \(bu 2
Now correctly adds parentheses when inner expressions are implicitly
converted multiple times.
.IP \(bu 2
Enabled the check for C99 and later standards.
.IP \(bu 2
Now allows implicit conversions from \fBbool\fP to integer when used as
operands of logical operators (\fB&&\fP, \fB||\fP) in C.
.UNINDENT
.IP \(bu 2
Improved readability\-inconsistent\-declaration\-parameter\-name \%<> check
by not enforcing parameter name consistency between a variadic parameter pack
in the primary template and specific parameters in its specializations.
.IP \(bu 2
Improved readability\-math\-missing\-parentheses \%<> check by correctly
diagnosing operator precedence issues inside parenthesized expressions.
.IP \(bu 2
Improved readability\-qualified\-auto \%<> check by adding the option
\fIIgnoreAliasing\fP, that allows not looking at underlying types of type aliases.
.IP \(bu 2
Improved readability\-redundant\-casting \%<> check by fixing false
negatives when explicitly cast from function pointer.
.IP \(bu 2
Improved readability\-redundant\-control\-flow \%<> by fixing an issue
where the check would sometimes suggest deleting not only a redundant
\fBreturn\fP or \fBcontinue\fP, but also unrelated lines preceding it.
.IP \(bu 2
Improved readability\-uppercase\-literal\-suffix \%<> check to recognize
literal suffixes added in C++23 and C23.
.IP \(bu 2
Improved readability\-use\-concise\-preprocessor\-directives \%<> check to
generate correct fix\-its for forms without a space after the directive.
.IP \(bu 2
Improved readability\-use\-std\-min\-max \%<> check by ensuring that
comments between the \fBif\fP condition and the \fBthen\fP block are preserved
when applying the fix.
.UNINDENT
.SS Removed checks
.SS Miscellaneous
.SS Improvements to include\-fixer
.sp
The improvements are...
.SS Improvements to clang\-include\-fixer
.sp
The improvements are...
.SS Improvements to modularize
.sp
The improvements are...
.SS Improvements to pp\-trace
.SS Clang\-tidy Visual Studio plugin
.SH CLANG-TIDY
.SS Contents
.INDENT 0.0
.IP \(bu 2
Clang\-Tidy
.INDENT 2.0
.IP \(bu 2
Using Clang\-Tidy
.IP \(bu 2
Clang\-Tidy Automation
.INDENT 2.0
.IP \(bu 2
Running Clang\-Tidy in Parallel
.IP \(bu 2
Running Clang\-Tidy on Diff
.UNINDENT
.IP \(bu 2
Suppressing Undesired Diagnostics
.UNINDENT
.UNINDENT
.sp
See also:
.SS Clang\-Tidy Checks
.SS abseil\-cleanup\-ctad
.sp
Suggests switching the initialization pattern of \fBabsl::Cleanup\fP
instances from the factory function to class template argument
deduction (CTAD), in C++17 and higher.
.INDENT 0.0
.INDENT 3.5
.sp
.EX
auto c1 = absl::MakeCleanup([] {});
const auto c2 = absl::MakeCleanup(std::function([] {}));
.EE
.UNINDENT
.UNINDENT
.sp
becomes
.INDENT 0.0
.INDENT 3.5
.sp
.EX
absl::Cleanup c1 = [] {};
const absl::Cleanup c2 = std::function([] {});
.EE
.UNINDENT
.UNINDENT
.SS abseil\-duration\-addition
.sp
Checks for cases where addition should be performed in the \fBabsl::Time\fP
domain. When adding two values, and one is known to be an \fBabsl::Time\fP,
we can infer that the other should be interpreted as an \fBabsl::Duration\fP
of a similar scale, and make that inference explicit.
.sp
Examples:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
// 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));
.EE
.UNINDENT
.UNINDENT
.SS abseil\-duration\-comparison
.sp
Checks for comparisons which should be in the \fBabsl::Duration\fP domain instead
of the floating point or integer domains.
.sp
N.B.: In cases where a \fBDuration\fP was being converted to an integer and then
compared against a floating\-point value, truncation during the \fBDuration\fP
conversion might yield a different result. In practice this is very rare, and
still indicates a bug which should be fixed.
.sp
Examples:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
// 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) ...
.EE
.UNINDENT
.UNINDENT
.SS abseil\-duration\-conversion\-cast
.sp
Checks for casts of \fBabsl::Duration\fP conversion functions, and recommends
the right conversion function instead.
.sp
Examples:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
// 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);
.EE
.UNINDENT
.UNINDENT
.sp
Note: In the second example, the suggested fix could yield a different result,
as the conversion to integer could truncate. In practice, this is very rare,
and you should use \fBabsl::Trunc\fP to perform this operation explicitly instead.
.SS abseil\-duration\-division
.sp
\fBabsl::Duration\fP arithmetic works like it does with integers. That means that
division of two \fBabsl::Duration\fP objects returns an \fBint64\fP with any
fractional component truncated toward 0.
See this link \%
for more information on arithmetic with \fBabsl::Duration\fP\&.
.sp
For example:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
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);
.EE
.UNINDENT
.UNINDENT
.sp
If you want floating\-point division, you should use either the
\fBabsl::FDivDuration()\fP function, or one of the unit conversion functions such
as \fBabsl::ToDoubleSeconds()\fP\&. For example:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
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);
.EE
.UNINDENT
.UNINDENT
.sp
This check looks for uses of \fBabsl::Duration\fP division that is done in a
floating\-point context, and recommends the use of a function that returns a
floating\-point value.
.SS abseil\-duration\-factory\-float
.sp
Checks for cases where the floating\-point overloads of various
\fBabsl::Duration\fP factory functions are called when the more\-efficient
integer versions could be used instead.
.sp
This check will not suggest fixes for literals which contain fractional
floating point values or non\-literals. It will suggest removing
superfluous casts.
.sp
Examples:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
// 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);
.EE
.UNINDENT
.UNINDENT
.SS abseil\-duration\-factory\-scale
.sp
Checks for cases where arguments to \fBabsl::Duration\fP factory functions are
scaled internally and could be changed to a different factory function. This
check also looks for arguments with a zero value and suggests using
\fBabsl::ZeroDuration()\fP instead.
.sp
Examples:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
// 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();
.EE
.UNINDENT
.UNINDENT
.SS abseil\-duration\-subtraction
.sp
Checks for cases where subtraction should be performed in the
\fBabsl::Duration\fP domain. When subtracting two values, and the first one is
known to be a conversion from \fBabsl::Duration\fP, we can infer that the second
should also be interpreted as an \fBabsl::Duration\fP, and make that inference
explicit.
.sp
Examples:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
// 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);
.EE
.UNINDENT
.UNINDENT
.sp
Note: As with other \fBclang\-tidy\fP checks, it is possible that multiple fixes
may overlap (as in the case of nested expressions), so not all occurrences can
be transformed in one run. In particular, this may occur for nested subtraction
expressions. Running \fBclang\-tidy\fP multiple times will find and fix these
overlaps.
.SS abseil\-duration\-unnecessary\-conversion
.sp
Finds and fixes cases where \fBabsl::Duration\fP values are being converted to
numeric types and back again.
.sp
Floating\-point examples:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
// 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;
.EE
.UNINDENT
.UNINDENT
.sp
Integer examples:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
// 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;
.EE
.UNINDENT
.UNINDENT
.sp
Unwrapping scalar operations:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
// 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;
.EE
.UNINDENT
.UNINDENT
.sp
Note: Converting to an integer and back to an \fBabsl::Duration\fP might be a
truncating operation if the value is not aligned to the scale of conversion.
In the rare case where this is the intended result, callers should use
\fBabsl::Trunc\fP to truncate explicitly.
.SS abseil\-faster\-strsplit\-delimiter
.sp
Finds instances of \fBabsl::StrSplit()\fP or \fBabsl::MaxSplits()\fP where the
delimiter is a single character string literal and replaces with a character.
The check will offer a suggestion to change the string literal into a
character. It will also catch code using \fBabsl::ByAnyChar()\fP for just a
single character and will transform that into a single character as well.
.sp
These changes will give the same result, but using characters rather than
single character string literals is more efficient and readable.
.sp
Examples:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
// Original \- the argument is a string literal.
for (auto piece : absl::StrSplit(str, \(dqB\(dq)) {
// Suggested \- the argument is a character, which causes the more efficient
// overload of absl::StrSplit() to be used.
for (auto piece : absl::StrSplit(str, \(aqB\(aq)) {
// Original \- the argument is a string literal inside absl::ByAnyChar call.
for (auto piece : absl::StrSplit(str, absl::ByAnyChar(\(dqB\(dq))) {
// 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, \(aqB\(aq)) {
// Original \- the argument is a string literal inside absl::MaxSplits call.
for (auto piece : absl::StrSplit(str, absl::MaxSplits(\(dqB\(dq, 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(\(aqB\(aq, 1))) {
.EE
.UNINDENT
.UNINDENT
.SS abseil\-no\-internal\-dependencies
.sp
Warns if code using Abseil depends on internal details. If something is in a
namespace that includes the word \(dqinternal\(dq, code is not allowed to depend upon
it because it\(aqs an implementation detail. They cannot friend it, include it,
you mention it or refer to it in any way. Doing so violates Abseil\(aqs
compatibility guidelines and may result in breakage. See
\% for more information.
.sp
The following cases will result in warnings:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
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
.EE
.UNINDENT
.UNINDENT
.SS abseil\-no\-namespace
.sp
Ensures code does not open \fBnamespace absl\fP as that violates Abseil\(aqs
compatibility guidelines. Code should not open \fBnamespace absl\fP as that
conflicts with Abseil\(aqs compatibility guidelines and may result in breakage.
.sp
Any code that uses:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
namespace absl {
...
}
.EE
.UNINDENT
.UNINDENT
.sp
will be prompted with a warning.
.sp
See the full Abseil compatibility guidelines \% for more information.
.SS abseil\-redundant\-strcat\-calls
.sp
Suggests removal of unnecessary calls to \fBabsl::StrCat\fP when the result is
being passed to another call to \fBabsl::StrCat\fP or \fBabsl::StrAppend\fP\&.
.sp
The extra calls cause unnecessary temporary strings to be constructed. Removing
them makes the code smaller and faster.
.sp
Examples:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
std::string s = absl::StrCat(\(dqA\(dq, absl::StrCat(\(dqB\(dq, absl::StrCat(\(dqC\(dq, \(dqD\(dq)));
//before
std::string s = absl::StrCat(\(dqA\(dq, \(dqB\(dq, \(dqC\(dq, \(dqD\(dq);
//after
absl::StrAppend(&s, absl::StrCat(\(dqE\(dq, \(dqF\(dq, \(dqG\(dq));
//before
absl::StrAppend(&s, \(dqE\(dq, \(dqF\(dq, \(dqG\(dq);
//after
.EE
.UNINDENT
.UNINDENT
.SS abseil\-str\-cat\-append
.sp
Flags uses of \fBabsl::StrCat()\fP to append to a \fBstd::string\fP\&. Suggests
\fBabsl::StrAppend()\fP should be used instead.
.sp
The extra calls cause unnecessary temporary strings to be constructed. Removing
them makes the code smaller and faster.
.INDENT 0.0
.INDENT 3.5
.sp
.EX
a = absl::StrCat(a, b); // Use absl::StrAppend(&a, b) instead.
.EE
.UNINDENT
.UNINDENT
.sp
Does not diagnose cases where \fBabsl::StrCat()\fP is used as a template
argument for a functor.
.SS abseil\-string\-find\-startswith
.sp
Checks whether a \fBstd::string::find()\fP or \fBstd::string::rfind()\fP (and
corresponding \fBstd::string_view\fP methods) result is compared with 0, and
suggests replacing with \fBabsl::StartsWith()\fP\&. This is both a readability and
performance issue.
.sp
\fBstarts_with\fP was added as a built\-in function on those types in C++20. If
available, prefer enabling modernize\-use\-starts\-ends\-with \%<> instead of this check.
.INDENT 0.0
.INDENT 3.5
.sp
.EX
string s = \(dq...\(dq;
if (s.find(\(dqHello World\(dq) == 0) { /* do something */ }
if (s.rfind(\(dqHello World\(dq, 0) == 0) { /* do something */ }
.EE
.UNINDENT
.UNINDENT
.sp
becomes
.INDENT 0.0
.INDENT 3.5
.sp
.EX
string s = \(dq...\(dq;
if (absl::StartsWith(s, \(dqHello World\(dq)) { /* do something */ }
if (absl::StartsWith(s, \(dqHello World\(dq)) { /* do something */ }
.EE
.UNINDENT
.UNINDENT
.SS Options
.INDENT 0.0
.TP
.B StringLikeClasses
Semicolon\-separated list of names of string\-like classes. By default both
\fBstd::basic_string\fP and \fBstd::basic_string_view\fP are considered. The list
of methods to be considered is fixed.
.UNINDENT
.INDENT 0.0
.TP
.B IncludeStyle
A string specifying which include\-style is used, \fIllvm\fP or \fIgoogle\fP\&. Default
is \fIllvm\fP\&.
.UNINDENT
.INDENT 0.0
.TP
.B AbseilStringsMatchHeader
The location of Abseil\(aqs \fBstrings/match.h\fP\&. Defaults to
\fBabsl/strings/match.h\fP\&.
.UNINDENT
.SS abseil\-string\-find\-str\-contains
.sp
Finds \fBs.find(...) == string::npos\fP comparisons (for various string\-like
types) and suggests replacing with \fBabsl::StrContains()\fP\&.
.sp
This improves readability and reduces the likelihood of accidentally mixing
\fBfind()\fP and \fBnpos\fP from different string\-like types.
.sp
By default, \(dqstring\-like types\(dq includes \fB::std::basic_string\fP,
\fB::std::basic_string_view\fP, and \fB::absl::string_view\fP\&. See the
StringLikeClasses option to change this.
.INDENT 0.0
.INDENT 3.5
.sp
.EX
std::string s = \(dq...\(dq;
if (s.find(\(dqHello World\(dq) == std::string::npos) { /* do something */ }
absl::string_view a = \(dq...\(dq;
if (absl::string_view::npos != a.find(\(dqHello World\(dq)) { /* do something */ }
.EE
.UNINDENT
.UNINDENT
.sp
becomes
.INDENT 0.0
.INDENT 3.5
.sp
.EX
std::string s = \(dq...\(dq;
if (!absl::StrContains(s, \(dqHello World\(dq)) { /* do something */ }
absl::string_view a = \(dq...\(dq;
if (absl::StrContains(a, \(dqHello World\(dq)) { /* do something */ }
.EE
.UNINDENT
.UNINDENT
.SS Options
.INDENT 0.0
.TP
.B StringLikeClasses
Semicolon\-separated list of names of string\-like classes. By default includes
\fB::std::basic_string\fP, \fB::std::basic_string_view\fP, and
\fB::absl::string_view\fP\&.
.UNINDENT
.INDENT 0.0
.TP
.B IncludeStyle
A string specifying which include\-style is used, \fIllvm\fP or \fIgoogle\fP\&. Default
is \fIllvm\fP\&.
.UNINDENT
.INDENT 0.0
.TP
.B AbseilStringsMatchHeader
The location of Abseil\(aqs \fBstrings/match.h\fP\&. Defaults to
\fBabsl/strings/match.h\fP\&.
.UNINDENT
.SS abseil\-time\-comparison
.sp
Prefer comparisons in the \fBabsl::Time\fP domain instead of the integer domain.
.sp
N.B.: In cases where an \fBabsl::Time\fP is being converted to an integer,
alignment may occur. If the comparison depends on this alignment, doing the
comparison in the \fBabsl::Time\fP domain may yield a different result. In
practice this is very rare, and still indicates a bug which should be fixed.
.sp
Examples:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
// 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) ...
.EE
.UNINDENT
.UNINDENT
.SS abseil\-time\-subtraction
.sp
Finds and fixes \fBabsl::Time\fP subtraction expressions to do subtraction
in the Time domain instead of the numeric domain.
.sp
There are two cases of Time subtraction in which deduce additional type
information:
.INDENT 0.0
.IP \(bu 2
When the result is an \fBabsl::Duration\fP and the first argument is an
\fBabsl::Time\fP\&.
.IP \(bu 2
When the second argument is a \fBabsl::Time\fP\&.
.UNINDENT
.sp
In the first case, we must know the result of the operation, since without that
the second operand could be either an \fBabsl::Time\fP or an \fBabsl::Duration\fP\&.
In the second case, the first operand \fImust\fP be an \fBabsl::Time\fP, because
subtracting an \fBabsl::Time\fP from an \fBabsl::Duration\fP is not defined.
.sp
Examples:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
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);
.EE
.UNINDENT
.UNINDENT
.SS abseil\-unchecked\-statusor\-access
.sp
This check identifies unsafe accesses to values contained in
\fBabsl::StatusOr\fP objects. Below we will refer to this type as
\fBStatusOr\fP\&.
.sp
An access to the value of an \fBStatusOr\fP occurs when one of its
\fBvalue\fP, \fBoperator*\fP, or \fBoperator\->\fP member functions is invoked.
To align with common misconceptions, the check considers these member
functions as equivalent, even though there are subtle differences
related to exceptions vs.\ undefined behavior.
.sp
An access to the value of a \fBStatusOr\fP is considered safe if and
only if code in the local scope (e.g.\ function body) ensures that the
status of the \fBStatusOr\fP is ok in all possible execution paths that
can reach the access. That should happen either through an explicit
check, using the \fBStatusOr::ok\fP member function, or by constructing
the \fBStatusOr\fP in a way that shows that its status is unambiguously
ok (e.g.\ by passing a value to its constructor).
.sp
Below we list some examples of safe and unsafe \fBStatusOr\fP access
patterns.
.sp
Note: If the check isn’t behaving as you would have expected on a code
snippet, please report it \%\&.
.SS False negatives
.sp
This check generally does \fBnot\fP generate false negatives. That means that if
an access is not marked as unsafe, it is provably safe. If it cannot prove an
access safe, it is assumed to be unsafe. In some cases, the static analysis
cannot prove an access safe even though it is, for a variety of reasons (e.g.
unmodelled invariants of functions called). In these cases, the analysis does
produce false positive reports.
.sp
That being said, there are some heuristics used that in very rare cases might
be incorrect:
.INDENT 0.0
.IP \(bu 2
a const method accessor (without arguments) that returns different
values when called multiple times \%<#\:functionstability>\&.
.UNINDENT
.sp
If you think the check generated a false negative, please report
it \%\&.
.SS Known limitations
.sp
This is a non\-exhaustive list of constructs that are currently not
modelled in the check and will lead to false positives:
.INDENT 0.0
.IP \(bu 2
Checking a StatusOr and then capturing it in a lambda \%<#\:lambdas>
.IP \(bu 2
Indexing into a container with the same index \%<#\:containers>
.IP \(bu 2
Project specific helper\-functions \%<#\:uncommonapi>,
.IP \(bu 2
Functions with a stable return value \%<#\:functionstability>
.IP \(bu 2
\fBAny\fP cross\-function reasoning \%<#\:crossfunction>\&. This is by
design and will not change in the future.
.UNINDENT
.SS Checking if the status is ok, then accessing the value
.sp
The check recognizes all straightforward ways for checking the status
and accessing the value contained in a \fBStatusOr\fP object. For
example:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
void f(absl::StatusOr sor) {
if (sor.ok()) {
use(*sor);
}
}
.EE
.UNINDENT
.UNINDENT
.SS Checking if the status is ok, then accessing the value from a copy
.sp
The criteria that the check uses is semantic, not syntactic. It
recognizes when a copy of the \fBStatusOr\fP object being accessed is
known to have ok status. For example:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
void f(absl::StatusOr sor1) {
if (sor1.ok()) {
absl::optional sor2 = sor1;
use(*sor2);
}
}
.EE
.UNINDENT
.UNINDENT
.SS Ensuring that the status is ok using common macros
.sp
The check is aware of common macros like \fBABSL_CHECK\fP and \fBASSERT_THAT\fP\&.
Those can be used to ensure that the status of a \fBStatusOr\fP object
is ok. For example:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
void f(absl::StatusOr sor) {
ABSL_DCHECK_OK(sor);
use(*sor);
}
.EE
.UNINDENT
.UNINDENT
.SS Ensuring that the status is ok, then accessing the value in a correlated branch
.sp
The check is aware of correlated branches in the code and can figure out
when a \fBStatusOr\fP object is ensured to have ok status on all
execution paths that lead to an access. For example:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
void f(absl::StatusOr sor) {
bool safe = false;
if (sor.ok() && SomeOtherCondition()) {
safe = true;
}
// ... more code...
if (safe) {
use(*sor);
}
}
.EE
.UNINDENT
.UNINDENT
.SS Accessing the value without checking the status
.sp
The check flags accesses to the value that are not locally guarded by a
status check:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
void f1(absl::StatusOr sor) {
use(*sor); // unsafe: it is unclear whether the status of \(gasor\(ga is ok.
}
void f2(absl::StatusOr sor) {
use(sor\->member); // unsafe: it is unclear whether the status of \(gasor\(ga is ok.
}
void f3(absl::StatusOr sor) {
use(sor.value()); // unsafe: it is unclear whether the status of \(gasor\(ga is ok.
}
.EE
.UNINDENT
.UNINDENT
.sp
Use \fBABSL_CHECK_OK\fP to signal that you knowingly want to crash on
non\-OK values.
.sp
NOTE: Even though using \fB\&.value()\fP on a non\-\fBok()\fP \fBStatusOr\fP is defined
to crash, it is often unintentional. That is why our checker flags those as
well.
.SS Accessing the value in the wrong branch
.sp
The check is aware of the state of a \fBStatusOr\fP object in different
branches of the code. For example:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
void f(absl::StatusOr sor) {
if (sor.ok()) {
} else {
use(*sor); // unsafe: it is clear that the status of \(gasor\(ga is *not* ok.
}
}
.EE
.UNINDENT
.UNINDENT
.SS Assuming a function result to be stable
.sp
The check is aware that function results might not be stable. That is,
consecutive calls to the same function might return different values.
For example:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
void f(Foo foo) {
if (foo.sor().ok()) {
use(*foo.sor()); // unsafe: it is unclear whether the status of \(gafoo.sor()\(ga is ok.
}
}
.EE
.UNINDENT
.UNINDENT
.sp
In such cases it is best to store the result of the function call in a
local variable and use it to access the value. For example:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
void f(Foo foo) {
if (const auto& foo_sor = foo.sor(); foo_sor.ok()) {
use(*foo_sor);
}
}
.EE
.UNINDENT
.UNINDENT
.sp
The check \fBdoes\fP assume that \fBconst\fP\-qualified accessor functions
return a stable value if no non\-const function was called between the
two calls:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
class Foo {
const absl::StatusOr& get() const {
[...];
}
}
void f(Foo foo) {
if (foo.get().ok()) {
use(*foo.get());
}
}
.EE
.UNINDENT
.UNINDENT
.sp
If there is a call to a non\-\fBconst\fP\-qualified function, the check
assumes the return value of the accessor was mutated.
.INDENT 0.0
.INDENT 3.5
.sp
.EX
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
}
}
.EE
.UNINDENT
.UNINDENT
.SS Relying on invariants of uncommon APIs
.sp
The check is unaware of invariants of uncommon APIs. For example:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
void f(Foo foo) {
if (foo.HasProperty(\(dqbar\(dq)) {
use(*foo.GetProperty(\(dqbar\(dq)); // unsafe: it is unclear whether the status of \(gafoo.GetProperty(\(dqbar\(dq)\(ga is ok.
}
}
.EE
.UNINDENT
.UNINDENT
.sp
In such cases it is best to check explicitly that the status of the
\fBStatusOr\fP object is ok. For example:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
void f(Foo foo) {
if (const auto& property = foo.GetProperty(\(dqbar\(dq); property.ok()) {
use(*property);
}
}
.EE
.UNINDENT
.UNINDENT
.SS Checking if the status is ok, then passing the \fBStatusOr\fP to another function
.sp
The check relies on local reasoning. The check and value access must
both happen in the same function. An access is considered unsafe even if
the caller of the function performing the access ensures that the status
of the \fBStatusOr\fP is ok. For example:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
void g(absl::StatusOr sor) {
use(*sor); // unsafe: it is unclear whether the status of \(gasor\(ga is ok.
}
void f(absl::StatusOr sor) {
if (sor.ok()) {
g(sor);
}
}
.EE
.UNINDENT
.UNINDENT
.sp
In such cases it is best to either pass the value directly when calling
a function or check that the status of the \fBStatusOr\fP is ok in the
local scope of the callee. For example:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
void g(int val) {
use(val);
}
void f(absl::StatusOr sor) {
if (sor.ok()) {
g(*sor);
}
}
.EE
.UNINDENT
.UNINDENT
.SS Aliases created via \fBusing\fP declarations
.sp
The check is aware of aliases of \fBStatusOr\fP types that are created
via \fBusing\fP declarations. For example:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
using StatusOrInt = absl::StatusOr;
void f(StatusOrInt sor) {
use(*sor); // unsafe: it is unclear whether the status of \(gasor\(ga is ok.
}
.EE
.UNINDENT
.UNINDENT
.SS Containers
.sp
The check is more strict than necessary when it comes to containers of
\fBStatusOr\fP values. Simply checking that the status of an element of
a container is ok is not sufficient to deem accessing it safe. For
example:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
void f(std::vector> sors) {
if (sors[0].ok()) {
use(*sors[0]); // unsafe: it is unclear whether the status of \(gasors[0]\(ga is ok.
}
}
.EE
.UNINDENT
.UNINDENT
.sp
One needs to grab a reference to a particular object and use that
instead:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
void f(std::vector> sors) {
absl::StatusOr& sor0 = sors[0];
if (sor0.ok()) {
use(*sor0);
}
}
.EE
.UNINDENT
.UNINDENT
.sp
A future version could improve the understanding of more safe usage
patterns that involve containers.
.SS Lambdas
.sp
The check is capable of reporting unsafe \fBStatusOr\fP accesses in
lambdas, but isn’t smart enough to propagate information from the
surrounding context through the lambda. This means that the following
pattern will be reported as an unsafe access:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
void f(absl::StatusOr sor) {
if (sor.ok()) {
[&sor]() {
use(*sor); // unsafe: it is unclear whether the status of \(gasor\(ga is ok.
}
}
}
.EE
.UNINDENT
.UNINDENT
.sp
To avoid the issue, you should grab a reference to the contained object
and capture that instead
.INDENT 0.0
.INDENT 3.5
.sp
.EX
void f(absl::StatusOr sor) {
if (sor.ok()) {
auto& s = *sor;
[&s]() {
use(s);
}
}
}
.EE
.UNINDENT
.UNINDENT
.sp
Alternatively you could add a check inside the lambda where the value is
accessed:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
void f(absl::StatusOr sor) {
[&sor]() {
if (sor.ok()) {
use(*sor);
}
}
}
.EE
.UNINDENT
.UNINDENT
.SS abseil\-upgrade\-duration\-conversions
.sp
Finds calls to \fBabsl::Duration\fP arithmetic operators and factories whose
argument needs an explicit cast to continue compiling after upcoming API
changes.
.sp
The operators \fB*=\fP, \fB/=\fP, \fB*\fP, and \fB/\fP for \fBabsl::Duration\fP currently
accept an argument of class type that is convertible to an arithmetic type.
Such a call currently converts the value to an \fBint64_t\fP, even in a case such
as \fBstd::atomic\fP that would result in lossy conversion.
.sp
Additionally, the \fBabsl::Duration\fP factory functions (\fBabsl::Hours\fP,
\fBabsl::Minutes\fP, etc) currently accept an \fBint64_t\fP or a floating\-point
type. Similar to the arithmetic operators, calls with an argument of class type
that is convertible to an arithmetic type go through the \fBint64_t\fP path.
.sp
These operators and factories will be changed to only accept arithmetic types
to prevent unintended behavior. After these changes are released, passing an
argument of class type will no longer compile, even if the type is implicitly
convertible to an arithmetic type.
.sp
Here are example fixes created by this check:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
std::atomic a;
absl::Duration d = absl::Milliseconds(a);
d *= a;
.EE
.UNINDENT
.UNINDENT
.sp
becomes
.INDENT 0.0
.INDENT 3.5
.sp
.EX
std::atomic a;
absl::Duration d = absl::Milliseconds(static_cast(a));
d *= static_cast(a);
.EE
.UNINDENT
.UNINDENT
.sp
Note that this check always adds a cast to \fBint64_t\fP in order to preserve the
current behavior of user code. It is possible that this uncovers unintended
behavior due to types implicitly convertible to a floating\-point type.
.SS altera\-id\-dependent\-backward\-branch
.sp
Finds ID\-dependent variables and fields that are used within loops. This causes
branches to occur inside the loops, and thus leads to performance degradation.
.INDENT 0.0
.INDENT 3.5
.sp
.EX
// 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;
}
.EE
.UNINDENT
.UNINDENT
.sp
Based on the Altera SDK for OpenCL: Best Practices Guide \%\&.
.SS altera\-kernel\-name\-restriction
.sp
Finds kernel files and include directives whose filename is \fIkernel.cl\fP,
\fIVerilog.cl\fP, or \fIVHDL.cl\fP\&. The check is case insensitive.
.sp
Such kernel file names cause the offline compiler to generate intermediate
design files that have the same names as certain internal files, which
leads to a compilation error.
.sp
Based on the \fIGuidelines for Naming the Kernel\fP section in the
Intel FPGA SDK for OpenCL Pro Edition: Programming Guide \%\&.
.SS altera\-single\-work\-item\-barrier
.sp
Finds OpenCL kernel functions that call a barrier function but do not call
an ID function (\fBget_local_id\fP, \fBget_local_id\fP, \fBget_group_id\fP, or
\fBget_local_linear_id\fP).
.sp
These kernels may be viable single work\-item kernels, but will be forced to
execute as NDRange kernels if using a newer version of the Altera Offline
Compiler (>= v17.01).
.sp
If using an older version of the Altera Offline Compiler, these kernel
functions will be treated as single work\-item kernels, which could be
inefficient or lead to errors if NDRange semantics were intended.
.sp
Based on the Altera SDK for OpenCL: Best Practices Guide \%\&.
.sp
Examples:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
// 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);
}
.EE
.UNINDENT
.UNINDENT
.SS Options
.INDENT 0.0
.TP
.B AOCVersion
Defines the version of the Altera Offline Compiler. Defaults to \fB1600\fP
(corresponding to version 16.00).
.UNINDENT
.SS altera\-struct\-pack\-align
.sp
Finds structs that are inefficiently packed or aligned, and recommends
packing and/or aligning of said structs as needed.
.sp
Structs that are not packed take up more space than they should, and accessing
structs that are not well aligned is inefficient.
.sp
Fix\-its are provided to fix both of these issues by inserting and/or amending
relevant struct attributes.
.sp
Based on the Altera SDK for OpenCL: Best Practices Guide \%\&.
.INDENT 0.0
.INDENT 3.5
.sp
.EX
// 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)));
.EE
.UNINDENT
.UNINDENT
.SS altera\-unroll\-loops
.sp
Finds inner loops that have not been unrolled, as well as fully unrolled loops
with unknown loop bounds or a large number of iterations.
.sp
Unrolling inner loops could improve the performance of OpenCL kernels. However,
if they have unknown loop bounds or a large number of iterations, they cannot
be fully unrolled, and should be partially unrolled.
.sp
Notes:
.INDENT 0.0
.IP \(bu 2
This check is unable to determine the number of iterations in a \fBwhile\fP or
\fBdo..while\fP loop; hence if such a loop is fully unrolled, a note is emitted
advising the user to partially unroll instead.
.IP \(bu 2
In \fBfor\fP loops, our check only works with simple arithmetic increments (
\fB+\fP, \fB\-\fP, \fB*\fP, \fB/\fP). For all other increments, partial unrolling is
advised.
.IP \(bu 2
Depending on the exit condition, the calculations for determining if the
number of iterations is large may be off by 1. This should not be an issue
since the cut\-off is generally arbitrary.
.UNINDENT
.sp
Based on the Altera SDK for OpenCL: Best Practices Guide \%\&.
.INDENT 0.0
.INDENT 3.5
.sp
.EX
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(\(dq%d\(dq, a);
}
#pragma unroll 5
// ok: this loop is large, but is partially unrolled
for (int a : A) {
printf(\(dq%d\(dq, a);
}
#pragma unroll
// warning: this loop is large and should be partially unrolled
for (int i = 0; i < 1000; ++i) {
printf(\(dq%d\(dq, i);
}
#pragma unroll 5
// ok: this loop is large, but is partially unrolled
for (int i = 0; i < 1000; ++i) {
printf(\(dq%d\(dq, i);
}
#pragma unroll
// warning: << operator not supported, recommend partial unrolling
for (int i = 0; i < 1000; i<<1) {
printf(\(dq%d\(dq, 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(\(dqIn loop\(dq);
}
#pragma unroll 5
// ok: loop may be large, but is partially unrolled
while (i < someVector.size()) {
someVector[i]++;
}
.EE
.UNINDENT
.UNINDENT
.SS Options
.INDENT 0.0
.TP
.B MaxLoopIterations
Defines the maximum number of loop iterations that a fully unrolled loop
can have. By default, it is set to \fI100\fP\&.
.sp
In practice, this refers to the integer value of the upper bound
within the loop statement\(aqs condition expression.
.UNINDENT
.SS android\-cloexec\-accept
.sp
The usage of \fBaccept()\fP is not recommended, it\(aqs better to use \fBaccept4()\fP\&.
Without this flag, an opened sensitive file descriptor would remain open across
a fork+exec to a lower\-privileged SELinux domain.
.sp
Examples:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
accept(sockfd, addr, addrlen);
// becomes
accept4(sockfd, addr, addrlen, SOCK_CLOEXEC);
.EE
.UNINDENT
.UNINDENT
.SS android\-cloexec\-accept4
.sp
\fBaccept4()\fP should include \fBSOCK_CLOEXEC\fP in its type argument to avoid the
file descriptor leakage. Without this flag, an opened sensitive file would
remain open across a fork+exec to a lower\-privileged SELinux domain.
.sp
Examples:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
accept4(sockfd, addr, addrlen, SOCK_NONBLOCK);
// becomes
accept4(sockfd, addr, addrlen, SOCK_NONBLOCK | SOCK_CLOEXEC);
.EE
.UNINDENT
.UNINDENT
.SS android\-cloexec\-creat
.sp
The usage of \fBcreat()\fP is not recommended, it\(aqs better to use \fBopen()\fP\&.
.sp
Examples:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
int fd = creat(path, mode);
// becomes
int fd = open(path, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, mode);
.EE
.UNINDENT
.UNINDENT
.SS android\-cloexec\-dup
.sp
The usage of \fBdup()\fP is not recommended, it\(aqs better to use \fBfcntl()\fP,
which can set the close\-on\-exec flag. Otherwise, an opened sensitive file would
remain open across a fork+exec to a lower\-privileged SELinux domain.
.sp
Examples:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
int fd = dup(oldfd);
// becomes
int fd = fcntl(oldfd, F_DUPFD_CLOEXEC);
.EE
.UNINDENT
.UNINDENT
.SS android\-cloexec\-epoll\-create
.sp
The usage of \fBepoll_create()\fP is not recommended, it\(aqs better to use
\fBepoll_create1()\fP, which allows close\-on\-exec.
.sp
Examples:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
epoll_create(size);
// becomes
epoll_create1(EPOLL_CLOEXEC);
.EE
.UNINDENT
.UNINDENT
.SS android\-cloexec\-epoll\-create1
.sp
\fBepoll_create1()\fP should include \fBEPOLL_CLOEXEC\fP in its type argument to
avoid the file descriptor leakage. Without this flag, an opened sensitive file
would remain open across a fork+exec to a lower\-privileged SELinux domain.
.sp
Examples:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
epoll_create1(0);
// becomes
epoll_create1(EPOLL_CLOEXEC);
.EE
.UNINDENT
.UNINDENT
.SS android\-cloexec\-fopen
.sp
\fBfopen()\fP should include \fBe\fP in their mode string; so \fBre\fP would be
valid. This is equivalent to having set \fBFD_CLOEXEC on\fP that descriptor.
.sp
Examples:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
fopen(\(dqfn\(dq, \(dqr\(dq);
// becomes
fopen(\(dqfn\(dq, \(dqre\(dq);
.EE
.UNINDENT
.UNINDENT
.SS android\-cloexec\-inotify\-init
.sp
The usage of \fBinotify_init()\fP is not recommended, it\(aqs better to use
\fBinotify_init1()\fP\&.
.sp
Examples:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
inotify_init();
// becomes
inotify_init1(IN_CLOEXEC);
.EE
.UNINDENT
.UNINDENT
.SS android\-cloexec\-inotify\-init1
.sp
\fBinotify_init1()\fP should include \fBIN_CLOEXEC\fP in its type argument
to avoid the file descriptor leakage. Without this flag, an opened
sensitive file would remain open across a fork+exec to a
lower\-privileged SELinux domain.
.sp
Examples:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
inotify_init1(IN_NONBLOCK);
// becomes
inotify_init1(IN_NONBLOCK | IN_CLOEXEC);
.EE
.UNINDENT
.UNINDENT
.SS android\-cloexec\-memfd\-create
.sp
\fBmemfd_create()\fP should include \fBMFD_CLOEXEC\fP in its type argument to avoid
the file descriptor leakage. Without this flag, an opened sensitive file would
remain open across a fork+exec to a lower\-privileged SELinux domain.
.sp
Examples:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
memfd_create(name, MFD_ALLOW_SEALING);
// becomes
memfd_create(name, MFD_ALLOW_SEALING | MFD_CLOEXEC);
.EE
.UNINDENT
.UNINDENT
.SS android\-cloexec\-open
.sp
A common source of security bugs is code that opens a file without using the
\fBO_CLOEXEC\fP flag. Without that flag, an opened sensitive file would remain
open across a fork+exec to a lower\-privileged SELinux domain, leaking that
sensitive data. Open\-like functions including \fBopen()\fP, \fBopenat()\fP, and
\fBopen64()\fP should include \fBO_CLOEXEC\fP in their flags argument.
.sp
Examples:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
open(\(dqfilename\(dq, O_RDWR);
open64(\(dqfilename\(dq, O_RDWR);
openat(0, \(dqfilename\(dq, O_RDWR);
// becomes
open(\(dqfilename\(dq, O_RDWR | O_CLOEXEC);
open64(\(dqfilename\(dq, O_RDWR | O_CLOEXEC);
openat(0, \(dqfilename\(dq, O_RDWR | O_CLOEXEC);
.EE
.UNINDENT
.UNINDENT
.SS android\-cloexec\-pipe
.sp
This check detects usage of \fBpipe()\fP\&. Using \fBpipe()\fP is not recommended,
\fBpipe2()\fP is the suggested replacement. The check also adds the \fBO_CLOEXEC\fP
flag that marks the file descriptor to be closed in child processes.
Without this flag a sensitive file descriptor can be leaked to a
child process, potentially into a lower\-privileged SELinux domain.
.sp
Examples:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
pipe(pipefd);
.EE
.UNINDENT
.UNINDENT
.sp
Suggested replacement:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
pipe2(pipefd, O_CLOEXEC);
.EE
.UNINDENT
.UNINDENT
.SS android\-cloexec\-pipe2
.sp
This check ensures that \fBpipe2()\fP is called with the \fBO_CLOEXEC\fP flag.
The check also adds the \fBO_CLOEXEC\fP flag that marks the file descriptor
to be closed in child processes.
Without this flag a sensitive file descriptor can be leaked to a child process,
potentially into a lower\-privileged SELinux domain.
.sp
Examples:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
pipe2(pipefd, O_NONBLOCK);
.EE
.UNINDENT
.UNINDENT
.sp
Suggested replacement:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
pipe2(pipefd, O_NONBLOCK | O_CLOEXEC);
.EE
.UNINDENT
.UNINDENT
.SS android\-cloexec\-socket
.sp
\fBsocket()\fP should include \fBSOCK_CLOEXEC\fP in its type argument to avoid the
file descriptor leakage. Without this flag, an opened sensitive file would
remain open across a fork+exec to a lower\-privileged SELinux domain.
.sp
Examples:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
socket(domain, type, SOCK_STREAM);
// becomes
socket(domain, type, SOCK_STREAM | SOCK_CLOEXEC);
.EE
.UNINDENT
.UNINDENT
.SS android\-comparison\-in\-temp\-failure\-retry
.sp
Diagnoses comparisons that appear to be incorrectly placed in the argument to
the \fBTEMP_FAILURE_RETRY\fP macro. Having such a use is incorrect in the vast
majority of cases, and will often silently defeat the purpose of the
\fBTEMP_FAILURE_RETRY\fP macro.
.sp
For context, \fBTEMP_FAILURE_RETRY\fP is a convenience macro \%
provided by both glibc and Bionic. Its purpose is to repeatedly run a syscall
until it either succeeds, or fails for reasons other than being interrupted.
.sp
Example buggy usage looks like:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
char cs[1];
while (TEMP_FAILURE_RETRY(read(STDIN_FILENO, cs, sizeof(cs)) != 0)) {
// Do something with cs.
}
.EE
.UNINDENT
.UNINDENT
.sp
Because \fBTEMP_FAILURE_RETRY\fP will check for whether the result
\fIof the comparison\fP is \fB\-1\fP, and retry if so.
.sp
If you encounter this, the fix is simple: lift the comparison out of the
\fBTEMP_FAILURE_RETRY\fP argument, like so:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
char cs[1];
while (TEMP_FAILURE_RETRY(read(STDIN_FILENO, cs, sizeof(cs))) != 0) {
// Do something with cs.
}
.EE
.UNINDENT
.UNINDENT
.SS Options
.INDENT 0.0
.TP
.B RetryMacros
A comma\-separated list of the names of retry macros to be checked.
Default is \fITEMP_FAILURE_RETRY\fP\&.
.UNINDENT
.SS boost\-use\-ranges
.sp
Detects calls to standard library iterator algorithms that could be replaced
with a Boost ranges version instead.
.SS Example
.INDENT 0.0
.INDENT 3.5
.sp
.EX
auto Iter1 = std::find(Items.begin(), Items.end(), 0);
auto AreSame = std::equal(Items1.cbegin(), Items1.cend(), std::begin(Items2),
std::end(Items2));
.EE
.UNINDENT
.UNINDENT
.sp
Transforms to:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
auto Iter1 = boost::range::find(Items, 0);
auto AreSame = boost::range::equal(Items1, Items2);
.EE
.UNINDENT
.UNINDENT
.SS Supported algorithms
.sp
Calls to the following std library algorithms are checked:
.sp
\fBstd::accumulate\fP,
\fBstd::adjacent_difference\fP,
\fBstd::adjacent_find\fP,
\fBstd::all_of\fP,
\fBstd::any_of\fP,
\fBstd::binary_search\fP,
\fBstd::copy_backward\fP,
\fBstd::copy_if\fP,
\fBstd::copy\fP,
\fBstd::count_if\fP,
\fBstd::count\fP,
\fBstd::equal_range\fP,
\fBstd::equal\fP,
\fBstd::fill\fP,
\fBstd::find_end\fP,
\fBstd::find_first_of\fP,
\fBstd::find_if_not\fP,
\fBstd::find_if\fP,
\fBstd::find\fP,
\fBstd::for_each\fP,
\fBstd::generate\fP,
\fBstd::includes\fP,
\fBstd::iota\fP,
\fBstd::is_partitioned\fP,
\fBstd::is_permutation\fP,
\fBstd::is_sorted_until\fP,
\fBstd::is_sorted\fP,
\fBstd::lexicographical_compare\fP,
\fBstd::lower_bound\fP,
\fBstd::make_heap\fP,
\fBstd::max_element\fP,
\fBstd::merge\fP,
\fBstd::min_element\fP,
\fBstd::mismatch\fP,
\fBstd::next_permutation\fP,
\fBstd::none_of\fP,
\fBstd::partial_sum\fP,
\fBstd::partial_sort_copy\fP,
\fBstd::partition_copy\fP,
\fBstd::partition_point\fP,
\fBstd::partition\fP,
\fBstd::pop_heap\fP,
\fBstd::prev_permutation\fP,
\fBstd::push_heap\fP,
\fBstd::random_shuffle\fP,
\fBstd::reduce\fP,
\fBstd::remove_copy_if\fP,
\fBstd::remove_copy\fP,
\fBstd::remove_if\fP,
\fBstd::remove\fP,
\fBstd::replace_copy_if\fP,
\fBstd::replace_copy\fP,
\fBstd::replace_if\fP,
\fBstd::replace\fP,
\fBstd::reverse_copy\fP,
\fBstd::reverse\fP,
\fBstd::search\fP,
\fBstd::set_difference\fP,
\fBstd::set_intersection\fP,
\fBstd::set_symmetric_difference\fP,
\fBstd::set_union\fP,
\fBstd::sort_heap\fP,
\fBstd::sort\fP,
\fBstd::stable_partition\fP,
\fBstd::stable_sort\fP,
\fBstd::transform\fP,
\fBstd::unique_copy\fP,
\fBstd::unique\fP,
\fBstd::upper_bound\fP\&.
.sp
The check will also look for the following functions from the
\fBboost::algorithm\fP namespace:
.sp
\fBall_of_equal\fP,
\fBany_of_equal\fP,
\fBany_of\fP,
\fBapply_permutation\fP,
\fBapply_reverse_permutation\fP,
\fBclamp_range\fP,
\fBcopy_if_until\fP,
\fBcopy_if_while\fP,
\fBcopy_if\fP,
\fBcopy_until\fP,
\fBcopy_while\fP,
\fBfind_backward\fP,
\fBfind_if_backward\fP,
\fBfind_if_not_backward\fP,
\fBfind_if_not\fP,
\fBfind_not_backward\fP,
\fBhex_lower\fP,
\fBhex\fP,
\fBiota\fP, \fBall_of\fP,
\fBis_decreasing\fP,
\fBis_increasing\fP,
\fBis_palindrome\fP,
\fBis_partitioned_until\fP,
\fBis_partitioned\fP,
\fBis_permutation\fP,
\fBis_sorted_until\fP,
\fBis_sorted\fP,
\fBis_strictly_decreasing\fP,
\fBis_strictly_increasing\fP,
\fBnone_of_equal\fP,
\fBnone_of\fP,
\fBone_of_equal\fP,
\fBone_of\fP,
\fBpartition_copy\fP,
\fBpartition_point\fP,
\fBreduce\fP,
\fBunhex\fP\&.
.SS Reverse Iteration
.sp
If calls are made using reverse iterators on containers, The code will be
fixed using the \fBboost::adaptors::reverse\fP adaptor.
.INDENT 0.0
.INDENT 3.5
.sp
.EX
auto AreSame = std::equal(Items1.rbegin(), Items1.rend(),
std::crbegin(Items2), std::crend(Items2));
.EE
.UNINDENT
.UNINDENT
.sp
Transforms to:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
auto AreSame = boost::range::equal(boost::adaptors::reverse(Items1),
boost::adaptors::reverse(Items2));
.EE
.UNINDENT
.UNINDENT
.SS Options
.INDENT 0.0
.TP
.B IncludeStyle
A string specifying which include\-style is used, \fIllvm\fP or \fIgoogle\fP\&. Default
is \fIllvm\fP\&.
.UNINDENT
.INDENT 0.0
.TP
.B IncludeBoostSystem
If \fItrue\fP (default value) the boost headers are included as system headers
with angle brackets (\fI#include \fP), otherwise quotes are used
(\fI#include \(dqboost.hpp\(dq\fP).
.UNINDENT
.INDENT 0.0
.TP
.B UseReversePipe
When \fItrue\fP (default \fIfalse\fP), fixes which involve reverse ranges will use the
pipe adaptor syntax instead of the function syntax.
.INDENT 7.0
.INDENT 3.5
.sp
.EX
std::find(Items.rbegin(), Items.rend(), 0);
.EE
.UNINDENT
.UNINDENT
.sp
Transforms to:
.INDENT 7.0
.INDENT 3.5
.sp
.EX
boost::range::find(Items | boost::adaptors::reversed, 0);
.EE
.UNINDENT
.UNINDENT
.UNINDENT
.SS boost\-use\-to\-string
.sp
This check finds conversion from integer type like \fBint\fP to
\fBstd::string\fP or \fBstd::wstring\fP using \fBboost::lexical_cast\fP,
and replace it with calls to \fBstd::to_string\fP and \fBstd::to_wstring\fP\&.
.sp
It doesn\(aqt replace conversion from floating points despite the \fBto_string\fP
overloads, because it would change the behavior.
.INDENT 0.0
.INDENT 3.5
.sp
.EX
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);
.EE
.UNINDENT
.UNINDENT
.SS bugprone\-argument\-comment
.sp
Checks that argument comments match parameter names.
.sp
The check understands argument comments in the form \fB/*parameter_name=*/\fP
that are placed right before the argument.
.INDENT 0.0
.INDENT 3.5
.sp
.EX
void f(bool foo);
\&...
f(/*bar=*/true);
// warning: argument name \(aqbar\(aq in comment does not match parameter name \(aqfoo\(aq
.EE
.UNINDENT
.UNINDENT
.sp
The check tries to detect typos and suggest automated fixes for them.
.SS Options
.INDENT 0.0
.TP
.B StrictMode
When \fIfalse\fP, the check will ignore leading and trailing
underscores and case when comparing names \-\- otherwise they are taken into
account. Default is \fIfalse\fP\&.
.UNINDENT
.INDENT 0.0
.TP
.B IgnoreSingleArgument
When \fItrue\fP, the check will ignore the single argument. Default is \fIfalse\fP\&.
.UNINDENT
.INDENT 0.0
.TP
.B CommentBoolLiterals
When \fItrue\fP, the check will add argument comments in the format
\fB/*ParameterName=*/\fP right before the boolean literal argument.
Default is \fIfalse\fP\&.
.UNINDENT
.sp
Before:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
void foo(bool TurnKey, bool PressButton);
foo(true, false);
.EE
.UNINDENT
.UNINDENT
.sp
After:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
void foo(bool TurnKey, bool PressButton);
foo(/*TurnKey=*/true, /*PressButton=*/false);
.EE
.UNINDENT
.UNINDENT
.INDENT 0.0
.TP
.B CommentIntegerLiterals
When \fItrue\fP, the check will add argument comments in the format
\fB/*ParameterName=*/\fP right before the integer literal argument.
Default is \fIfalse\fP\&.
.UNINDENT
.sp
Before:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
void foo(int MeaningOfLife);
foo(42);
.EE
.UNINDENT
.UNINDENT
.sp
After:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
void foo(int MeaningOfLife);
foo(/*MeaningOfLife=*/42);
.EE
.UNINDENT
.UNINDENT
.INDENT 0.0
.TP
.B CommentFloatLiterals
When \fItrue\fP, the check will add argument comments in the format
\fB/*ParameterName=*/\fP right before the float/double literal argument.
Default is \fIfalse\fP\&.
.UNINDENT
.sp
Before:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
void foo(float Pi);
foo(3.14159);
.EE
.UNINDENT
.UNINDENT
.sp
After:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
void foo(float Pi);
foo(/*Pi=*/3.14159);
.EE
.UNINDENT
.UNINDENT
.INDENT 0.0
.TP
.B CommentStringLiterals
When \fItrue\fP, the check will add argument comments in the format
\fB/*ParameterName=*/\fP right before the string literal argument.
Default is \fIfalse\fP\&.
.UNINDENT
.sp
Before:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
void foo(const char *String);
void foo(const wchar_t *WideString);
foo(\(dqHello World\(dq);
foo(L\(dqHello World\(dq);
.EE
.UNINDENT
.UNINDENT
.sp
After:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
void foo(const char *String);
void foo(const wchar_t *WideString);
foo(/*String=*/\(dqHello World\(dq);
foo(/*WideString=*/L\(dqHello World\(dq);
.EE
.UNINDENT
.UNINDENT
.INDENT 0.0
.TP
.B CommentCharacterLiterals
When \fItrue\fP, the check will add argument comments in the format
\fB/*ParameterName=*/\fP right before the character literal argument.
Default is \fIfalse\fP\&.
.UNINDENT
.sp
Before:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
void foo(char *Character);
foo(\(aqA\(aq);
.EE
.UNINDENT
.UNINDENT
.sp
After:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
void foo(char *Character);
foo(/*Character=*/\(aqA\(aq);
.EE
.UNINDENT
.UNINDENT
.INDENT 0.0
.TP
.B CommentUserDefinedLiterals
When \fItrue\fP, the check will add argument comments in the format
\fB/*ParameterName=*/\fP right before the user defined literal argument.
Default is \fIfalse\fP\&.
.UNINDENT
.sp
Before:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
void foo(double Distance);
double operator\(dq\(dq _km(long double);
foo(402.0_km);
.EE
.UNINDENT
.UNINDENT
.sp
After:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
void foo(double Distance);
double operator\(dq\(dq _km(long double);
foo(/*Distance=*/402.0_km);
.EE
.UNINDENT
.UNINDENT
.INDENT 0.0
.TP
.B CommentNullPtrs
When \fItrue\fP, the check will add argument comments in the format
\fB/*ParameterName=*/\fP right before the nullptr literal argument.
Default is \fIfalse\fP\&.
.UNINDENT
.sp
Before:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
void foo(A* Value);
foo(nullptr);
.EE
.UNINDENT
.UNINDENT
.sp
After:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
void foo(A* Value);
foo(/*Value=*/nullptr);
.EE
.UNINDENT
.UNINDENT
.SS bugprone\-assert\-side\-effect
.sp
Finds \fBassert()\fP with side effect.
.sp
The condition of \fBassert()\fP is evaluated only in debug builds so a
condition with side effect can cause different behavior in debug / release
builds.
.SS Options
.INDENT 0.0
.TP
.B AssertMacros
A comma\-separated list of the names of assert macros to be checked.
Default is \fIassert,NSAssert,NSCAssert\fP\&.
.UNINDENT
.INDENT 0.0
.TP
.B CheckFunctionCalls
Whether to treat non\-const member and non\-member functions as they produce
side effects. Disabled by default because it can increase the number of false
positive warnings.
.UNINDENT
.INDENT 0.0
.TP
.B IgnoredFunctions
A semicolon\-separated list of the names of functions or methods to be
considered as not having side\-effects. Regular expressions are accepted,
e.g. \fB[Rr]ef(erence)?$\fP matches every type with suffix \fBRef\fP, \fBref\fP,
\fBReference\fP and \fBreference\fP\&. The default is empty. If a name in the list
contains the sequence \fI::\fP it is matched against the qualified type name
(i.e. \fBnamespace::Type\fP), otherwise it is matched against only
the type name (i.e. \fBType\fP).
.UNINDENT
.SS bugprone\-assignment\-in\-if\-condition
.sp
Finds assignments within conditions of \fIif\fP statements.
Such assignments are bug\-prone because they may have been intended as
equality tests.
.sp
This check finds all assignments within \fIif\fP conditions, including ones that
are not flagged by \fI\-Wparentheses\fP due to an extra set of parentheses, and
including assignments that call an overloaded \fBoperator=()\fP\&. The identified
assignments violate
BARR group \(dqRule 8.2.c\(dq \%\&.
.INDENT 0.0
.INDENT 3.5
.sp
.EX
int f = 3;
if(f = 4) { // This is identified by both \(gaWparentheses\(ga and this check \- should it have been: \(gaif (f == 4)\(ga ?
f = f + 1;
}
if((f == 5) || (f = 6)) { // the assignment here \(ga(f = 6)\(ga is identified by this check, but not by \(ga\-Wparentheses\(ga. Should it have been \(ga(f == 6)\(ga ?
f = f + 2;
}
.EE
.UNINDENT
.UNINDENT
.SS bugprone\-bad\-signal\-to\-kill\-thread
.sp
Finds \fBpthread_kill\fP function calls when a thread is terminated by
raising \fBSIGTERM\fP signal and the signal kills the entire process, not
just the individual thread. Use any signal except \fBSIGTERM\fP\&.
.INDENT 0.0
.INDENT 3.5
.sp
.EX
pthread_kill(thread, SIGTERM);
.EE
.UNINDENT
.UNINDENT
.sp
This check corresponds to the CERT C Coding Standard rule
POS44\-C. Do not use signals to terminate threads \%\&.
.sp
\fIcert\-pos44\-c\fP redirects here as an alias of this check.
.SS bugprone\-bitwise\-pointer\-cast
.sp
Warns about code that tries to cast between pointers by means of
\fBstd::bit_cast\fP or \fBmemcpy\fP\&.
.sp
The motivation is that \fBstd::bit_cast\fP is advertised as the safe alternative
to type punning via \fBreinterpret_cast\fP in modern C++. However, one should not
blindly replace \fBreinterpret_cast\fP with \fBstd::bit_cast\fP, as follows:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
int x{};
\-float y = *reinterpret_cast(&x);
+float y = *std::bit_cast(&x);
.EE
.UNINDENT
.UNINDENT
.sp
The drop\-in replacement behaves exactly the same as \fBreinterpret_cast\fP, and
Undefined Behavior is still invoked. \fBstd::bit_cast\fP is copying the bytes of
the input pointer, not the pointee, into an output pointer of a different type,
which may violate the strict aliasing rules. However, simply looking at the
code, it looks \(dqsafe\(dq, because it uses \fBstd::bit_cast\fP which is advertised as
safe.
.sp
The solution to safe type punning is to apply \fBstd::bit_cast\fP on value types,
not on pointer types:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
int x{};
float y = std::bit_cast(x);
.EE
.UNINDENT
.UNINDENT
.sp
This way, the bytes of the input object are copied into the output object,
which is much safer. Do note that Undefined Behavior can still occur, if there
is no value of type \fBTo\fP corresponding to the value representation produced.
Compilers may be able to optimize this copy and generate identical assembly to
the original \fBreinterpret_cast\fP version.
.sp
Code before C++20 may backport \fBstd::bit_cast\fP by means of \fBmemcpy\fP, or
simply call \fBmemcpy\fP directly, which is equally problematic. This is also
detected by this check:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
int* x{};
float* y{};
std::memcpy(&y, &x, sizeof(x));
.EE
.UNINDENT
.UNINDENT
.sp
Alternatively, if a cast between pointers is truly wanted, \fBreinterpret_cast\fP
should be used, to clearly convey the intent and enable warnings from compilers
and linters, which should be addressed accordingly.
.SS bugprone\-bool\-pointer\-implicit\-conversion
.sp
Checks for conditions based on implicit conversion from a \fBbool\fP pointer to
\fBbool\fP\&.
.sp
Example:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
bool *p;
if (p) {
// Never used in a pointer\-specific way.
}
.EE
.UNINDENT
.UNINDENT
.SS bugprone\-branch\-clone
.sp
Checks for repeated branches in \fBif/else if/else\fP chains, consecutive
repeated branches in \fBswitch\fP statements and identical true and false
branches in conditional operators.
.INDENT 0.0
.INDENT 3.5
.sp
.EX
if (test_value(x)) {
y++;
do_something(x, y);
} else {
y++;
do_something(x, y);
}
.EE
.UNINDENT
.UNINDENT
.sp
In this simple example (which could arise e.g. as a copy\-paste error) the
\fBthen\fP and \fBelse\fP branches are identical and the code is equivalent the
following shorter and cleaner code:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
test_value(x); // can be omitted unless it has side effects
y++;
do_something(x, y);
.EE
.UNINDENT
.UNINDENT
.sp
If this is the intended behavior, then there is no reason to use a conditional
statement; otherwise the issue can be solved by fixing the branch that is
handled incorrectly.
.sp
The check detects repeated branches in longer \fBif/else if/else\fP chains
where it would be even harder to notice the problem.
.sp
The check also detects repeated inner and outer \fBif\fP statements that may
be a result of a copy\-paste error. This check cannot currently detect
identical inner and outer \fBif\fP statements if code is between the \fBif\fP
conditions. An example is as follows.
.INDENT 0.0
.INDENT 3.5
.sp
.EX
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)
;
}
}
.EE
.UNINDENT
.UNINDENT
.sp
In \fBswitch\fP statements the check only reports repeated branches when they are
consecutive, because it is relatively common that the \fBcase:\fP labels have
some natural ordering and rearranging them would decrease the readability of
the code. For example:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
switch (ch) {
case \(aqa\(aq:
return 10;
case \(aqA\(aq:
return 10;
case \(aqb\(aq:
return 11;
case \(aqB\(aq:
return 11;
default:
return 10;
}
.EE
.UNINDENT
.UNINDENT
.sp
Here the check reports that the \fB\(aqa\(aq\fP and \fB\(aqA\(aq\fP branches are identical
(and that the \fB\(aqb\(aq\fP and \fB\(aqB\(aq\fP branches are also identical), but does not
report that the \fBdefault:\fP branch is also identical to the first two branches.
If this is indeed the correct behavior, then it could be implemented as:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
switch (ch) {
case \(aqa\(aq:
case \(aqA\(aq:
return 10;
case \(aqb\(aq:
case \(aqB\(aq:
return 11;
default:
return 10;
}
.EE
.UNINDENT
.UNINDENT
.sp
Here the check does not warn for the repeated \fBreturn 10;\fP, which is good if
we want to preserve that \fB\(aqa\(aq\fP is before \fB\(aqb\(aq\fP and \fBdefault:\fP is the last
branch.
.sp
Switch cases marked with the \fB[[fallthrough]]\fP attribute are ignored.
.sp
Finally, the check also examines conditional operators and reports code like:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
return test_value(x) ? x : x;
.EE
.UNINDENT
.UNINDENT
.sp
Unlike if statements, the check does not detect chains of conditional
operators.
.sp
Note: This check also reports situations where branches become identical only
after preprocessing.
.SS bugprone\-capturing\-this\-in\-member\-variable
.sp
Finds lambda captures that capture the \fBthis\fP pointer and store it as class
members without handle the copy and move constructors and the assignments.
.sp
Capture this in a lambda and store it as a class member is dangerous because
the lambda can outlive the object it captures. Especially when the object is
copied or moved, the captured \fBthis\fP pointer will be implicitly propagated
to the new object. Most of the time, people will believe that the captured
\fBthis\fP pointer points to the new object, which will lead to bugs.
.INDENT 0.0
.INDENT 3.5
.sp
.EX
struct C {
C() : Captured([this]() \-> C const * { return this; }) {}
std::function Captured;
};
void foo() {
C v1{};
C v2 = v1; // v2.Captured capture v1\(aqs \(aqthis\(aq pointer
assert(v2.Captured() == v1.Captured()); // v2.Captured capture v1\(aqs \(aqthis\(aq pointer
assert(v2.Captured() == &v2); // assertion failed.
}
.EE
.UNINDENT
.UNINDENT
.INDENT 0.0
.TP
.B Possible fixes:
.INDENT 7.0
.IP \(bu 2
marking copy and move constructors and assignment operators deleted.
.IP \(bu 2
using class member method instead of class member variable with function
object types.
.IP \(bu 2
passing \fBthis\fP pointer as parameter.
.UNINDENT
.UNINDENT
.SS Options
.INDENT 0.0
.TP
.B FunctionWrapperTypes
A semicolon\-separated list of names of types. Used to specify function
wrapper that can hold lambda expressions.
Default is \fI::std::function;::std::move_only_function;::boost::function\fP\&.
.UNINDENT
.INDENT 0.0
.TP
.B BindFunctions
A semicolon\-separated list of fully qualified names of functions that can
capture \fBthis\fP pointer.
Default is \fI::std::bind;::boost::bind;::std::bind_front;::std::bind_back;
::boost::compat::bind_front;::boost::compat::bind_back\fP\&.
.UNINDENT
.SS bugprone\-casting\-through\-void
.sp
Detects unsafe or redundant two\-step casting operations involving \fBvoid*\fP,
which is equivalent to \fBreinterpret_cast\fP as per the
C++ Standard \%\&.
.sp
Two\-step type conversions via \fBvoid*\fP are discouraged for several reasons.
.INDENT 0.0
.IP \(bu 2
They obscure code and impede its understandability, complicating maintenance.
.IP \(bu 2
These conversions bypass valuable compiler support, erasing warnings related
to pointer alignment. It may violate strict aliasing rule and leading to
undefined behavior.
.IP \(bu 2
In scenarios involving multiple inheritance, ambiguity and unexpected
outcomes can arise due to the loss of type information, posing runtime
issues.
.UNINDENT
.sp
In summary, avoiding two\-step type conversions through \fBvoid*\fP ensures
clearer code, maintains essential compiler warnings, and prevents ambiguity
and potential runtime errors, particularly in complex inheritance scenarios.
If such a cast is wanted, it shall be done via \fBreinterpret_cast\fP,
to express the intent more clearly.
.sp
Note: it is expected that, after applying the suggested fix and using
\fBreinterpret_cast\fP, the check
cppcoreguidelines\-pro\-type\-reinterpret\-cast \%<> will emit a warning.
This is intentional: \fBreinterpret_cast\fP is a dangerous operation that can
easily break the strict aliasing rules when dereferencing the casted pointer,
invoking Undefined Behavior. The warning is there to prompt users to carefully
analyze whether the usage of \fBreinterpret_cast\fP is safe, in which case the
warning may be suppressed.
.sp
Examples:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
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.
.EE
.UNINDENT
.UNINDENT
.SS bugprone\-chained\-comparison
.sp
Check detects chained comparison operators that can lead to unintended
behavior or logical errors.
.sp
Chained comparisons are expressions that use multiple comparison operators
to compare three or more values. For example, the expression \fBa < b < c\fP
compares the values of \fBa\fP, \fBb\fP, and \fBc\fP\&. However, this expression does
not evaluate as \fB(a < b) && (b < c)\fP, which is probably what the developer
intended. Instead, it evaluates as \fB(a < b) < c\fP, which may produce
unintended results, especially when the types of \fBa\fP, \fBb\fP, and \fBc\fP are
different.
.sp
To avoid such errors, the check will issue a warning when a chained
comparison operator is detected, suggesting to use parentheses to specify
the order of evaluation or to use a logical operator to separate comparison
expressions.
.sp
Consider the following examples:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
int a = 2, b = 6, c = 4;
if (a < b < c) {
// This block will be executed
}
.EE
.UNINDENT
.UNINDENT
.sp
In this example, the developer intended to check if \fBa\fP is less than \fBb\fP
and \fBb\fP is less than \fBc\fP\&. However, the expression \fBa < b < c\fP is
equivalent to \fB(a < b) < c\fP\&. Since \fBa < b\fP is \fBtrue\fP, the expression
\fB(a < b) < c\fP is evaluated as \fB1 < c\fP, which is equivalent to \fBtrue < c\fP
and is invalid in this case as \fBb < c\fP is \fBfalse\fP\&.
.sp
Even that above issue could be detected as comparison of \fBint\fP to \fBbool\fP,
there is more dangerous example:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
bool a = false, b = false, c = true;
if (a == b == c) {
// This block will be executed
}
.EE
.UNINDENT
.UNINDENT
.sp
In this example, the developer intended to check if \fBa\fP, \fBb\fP, and \fBc\fP are
all equal. However, the expression \fBa == b == c\fP is evaluated as
\fB(a == b) == c\fP\&. Since \fBa == b\fP is true, the expression \fB(a == b) == c\fP
is evaluated as \fBtrue == c\fP, which is equivalent to \fBtrue == true\fP\&.
This comparison yields \fBtrue\fP, even though \fBa\fP and \fBb\fP are \fBfalse\fP, and
are not equal to \fBc\fP\&.
.sp
To avoid this issue, the developer can use a logical operator to separate the
comparison expressions, like this:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
if (a == b && b == c) {
// This block will not be executed
}
.EE
.UNINDENT
.UNINDENT
.sp
Alternatively, use of parentheses in the comparison expressions can make the
developer\(aqs intention more explicit and help avoid misunderstanding.
.INDENT 0.0
.INDENT 3.5
.sp
.EX
if ((a == b) == c) {
// This block will be executed
}
.EE
.UNINDENT
.UNINDENT
.SS Options
.INDENT 0.0
.TP
.B IgnoreMacros
If \fItrue\fP, the check will not warn on chained comparisons inside macros.
Default is \fIfalse\fP\&.
.UNINDENT
.SS bugprone\-command\-processor
.sp
Flags calls to \fBsystem()\fP, \fBpopen()\fP, and \fB_popen()\fP, which
execute a command processor. It does not flag calls to \fBsystem()\fP with a null
pointer argument, as such a call checks for the presence of a command processor
but does not actually attempt to execute a command.
.SS References
.sp
This check corresponds to the CERT C Coding Standard rule
ENV33\-C. Do not call system() \%\&.
.SS bugprone\-compare\-pointer\-to\-member\-virtual\-function
.sp
Detects unspecified behavior about equality comparison between pointer to
member virtual function and anything other than null\-pointer\-constant.
.INDENT 0.0
.INDENT 3.5
.sp
.EX
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.
}
.EE
.UNINDENT
.UNINDENT
.sp
Provide warnings on equality comparisons involve pointers to member virtual
function or variables which is potential pointer to member virtual function and
any entity other than a null\-pointer constant.
.sp
In certain compilers, virtual function addresses are not conventional pointers
but instead consist of offsets and indexes within a virtual function table
(vtable). Consequently, these pointers may vary between base and derived
classes, leading to unpredictable behavior when compared directly. This issue
becomes particularly challenging when dealing with pointers to pure virtual
functions, as they may not even have a valid address, further complicating
comparisons.
.sp
Instead, it is recommended to utilize the \fBtypeid\fP operator or other
appropriate mechanisms for comparing objects to ensure robust and predictable
behavior in your codebase. By heeding this detection and adopting a more reliable
comparison method, you can mitigate potential issues related to unspecified
behavior, especially when dealing with pointers to member virtual functions or pure
virtual functions, thereby improving the overall stability and maintainability
of your code. In scenarios involving pointers to member virtual functions, it\(aqs
only advisable to employ \fBnullptr\fP for comparisons.
.SS Limitations
.sp
Does not analyze values stored in a variable. For variable, only analyze all
virtual methods in the same \fBclass\fP or \fBstruct\fP and diagnose when assigning
a pointer to member virtual function to this variable is possible.
.SS bugprone\-copy\-constructor\-init
.sp
Finds copy constructors where the constructor doesn\(aqt call the copy constructor
of the base class.
.INDENT 0.0
.INDENT 3.5
.sp
.EX
class Copyable {
public:
Copyable() = default;
Copyable(const Copyable &) = default;
int memberToBeCopied = 0;
};
class X2 : public Copyable {
X2(const X2 &other) {} // Copyable(other) is missing
};
.EE
.UNINDENT
.UNINDENT
.sp
Also finds copy constructors where the constructor of
the base class don\(aqt have parameter.
.INDENT 0.0
.INDENT 3.5
.sp
.EX
class X3 : public Copyable {
X3(const X3 &other) : Copyable() {} // other is missing
};
.EE
.UNINDENT
.UNINDENT
.sp
Failure to properly initialize base class sub\-objects during copy construction
can result in undefined behavior, crashes, data corruption, or other unexpected
outcomes. The check ensures that the copy constructor of a derived class
properly calls the copy constructor of the base class, helping to prevent bugs
and improve code quality.
.SS Limitations
.INDENT 0.0
.IP \(bu 2
It won\(aqt generate warnings for empty classes, as there are no class members
(including base class sub\-objects) to worry about.
.IP \(bu 2
It won\(aqt generate warnings for base classes that have copy constructor
private or deleted.
.IP \(bu 2
It won\(aqt generate warnings for base classes that are initialized using other
non\-default constructor, as this could be intentional.
.UNINDENT
.sp
The check also suggests a fix\-its in some cases.
.SS bugprone\-copy\-constructor\-mutates\-argument
.sp
Finds assignments to the copied object and its direct or indirect members
in copy constructors and copy assignment operators.
.sp
This check corresponds to the CERT C Coding Standard rule
OOP58\-CPP. Copy operations must not mutate the source object \%\&.
.SS bugprone\-crtp\-constructor\-accessibility
.sp
Detects error\-prone Curiously Recurring Template Pattern usage, when the CRTP
can be constructed outside itself and the derived class.
.sp
The CRTP is an idiom, in which a class derives from a template class, where
itself is the template argument. It should be ensured that if a class is
intended to be a base class in this idiom, it can only be instantiated if
the derived class is its template argument.
.sp
Example:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
template class CRTP {
private:
CRTP() = default;
friend T;
};
class Derived : CRTP {};
.EE
.UNINDENT
.UNINDENT
.sp
Below can be seen some common mistakes that will allow the breaking of the
idiom.
.sp
If the constructor of a class intended to be used in a CRTP is public, then
it allows users to construct that class on its own.
.sp
Example:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
template class CRTP {
public:
CRTP() = default;
};
class Good : CRTP {};
Good GoodInstance;
CRTP BadInstance;
.EE
.UNINDENT
.UNINDENT
.sp
If the constructor is protected, the possibility of an accidental instantiation
is prevented, however it can fade an error, when a different class is used as
the template parameter instead of the derived one.
.sp
Example:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
template class CRTP {
protected:
CRTP() = default;
};
class Good : CRTP {};
Good GoodInstance;
class Bad : CRTP {};
Bad BadInstance;
.EE
.UNINDENT
.UNINDENT
.sp
To ensure that no accidental instantiation happens, the best practice is to
make the constructor private and declare the derived class as friend. Note
that as a tradeoff, this also gives the derived class access to every other
private members of the CRTP. However, constructors can still be public or
protected if they are deleted.
.sp
Example:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
template class CRTP {
CRTP() = default;
friend T;
};
class Good : CRTP {};
Good GoodInstance;
class Bad : CRTP {};
Bad CompileTimeError;
CRTP AlsoCompileTimeError;
.EE
.UNINDENT
.UNINDENT
.SS Limitations
.INDENT 0.0
.IP \(bu 2
The check is not supported below C++11
.IP \(bu 2
The check does not handle when the derived class is passed as a variadic
template argument
.IP \(bu 2
Accessible functions that can construct the CRTP, like factory functions
are not checked
.UNINDENT
.sp
The check also suggests a fix\-its in some cases.
.SS bugprone\-dangling\-handle
.sp
Detect dangling references in value handles like \fBstd::string_view\fP\&.
These dangling references can be a result of constructing handles from
temporary values, where the temporary is destroyed soon after the handle
is created.
.sp
Examples:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
string_view View = string(); // View will dangle.
string A;
View = A + \(dqA\(dq; // 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};
}
.EE
.UNINDENT
.UNINDENT
.SS Options
.INDENT 0.0
.TP
.B HandleClasses
A semicolon\-separated list of class names that should be treated as handles.
By default only \fBstd::basic_string_view\fP,
\fBstd::experimental::basic_string_view\fP and \fBstd::span\fP are considered.
.UNINDENT
.SS bugprone\-default\-operator\-new\-on\-overaligned\-type
.sp
Flags uses of default \fBoperator new\fP where the type has extended
alignment (an alignment greater than the fundamental alignment).
.sp
The default \fBoperator new\fP is guaranteed to provide the correct alignment
if the requested alignment is less or equal to the fundamental alignment.
Only cases are detected (by design) where the \fBoperator new\fP is not
user\-defined and is not a placement new (the reason is that in these cases we
assume that the user provided the correct memory allocation).
.SS References
.sp
This check corresponds to the CERT C++ Coding Standard rule
MEM57\-CPP. Avoid using default operator new for over\-aligned types \%\&.
.SS bugprone\-derived\-method\-shadowing\-base\-method
.sp
Finds derived class methods that shadow a (non\-virtual) base class method.
.sp
In order to be considered \(dqshadowing\(dq, methods must have the same signature
(i.e. the same name, same number of parameters, same parameter types, etc).
Only checks public, non\-templated methods.
.sp
The below example is bugprone because consumers of the \fBDerived\fP class will
expect the \fBreset\fP method to do the work of \fBBase::reset()\fP in addition to
extra work required to reset the \fBDerived\fP class. Common fixes include:
.INDENT 0.0
.IP \(bu 2
Making the \fBreset\fP method polymorphic
.IP \(bu 2
Re\-naming \fBDerived::reset\fP if it\(aqs not meant to intersect with
\fBBase::reset\fP
.IP \(bu 2
Using \fBusing Base::reset\fP to change the access specifier
.UNINDENT
.sp
This is also a violation of the Liskov Substitution Principle.
.INDENT 0.0
.INDENT 3.5
.sp
.EX
struct Base {
void reset() {/* reset the base class */};
};
struct Derived : public Base {
void reset() {/* reset the derived class, but not the base class */};
};
.EE
.UNINDENT
.UNINDENT
.SS bugprone\-dynamic\-static\-initializers
.sp
Finds instances of static variables that are dynamically initialized
in header files.
.sp
This can pose problems in certain multithreaded contexts. For example,
when disabling compiler generated synchronization instructions for
static variables initialized at runtime (e.g. by \fB\-fno\-threadsafe\-statics\fP),
even if a particular project takes the necessary precautions to prevent race
conditions during initialization by providing their own synchronization, header
files included from other projects may not. Therefore, such a check is helpful
for ensuring that disabling compiler generated synchronization for static
variable initialization will not cause problems.
.sp
Consider the following code:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
int foo() {
static int k = bar();
return k;
}
.EE
.UNINDENT
.UNINDENT
.sp
When synchronization of static initialization is disabled, if two threads both
call \fIfoo\fP for the first time, there is the possibility that \fIk\fP will be double
initialized, creating a race condition.
.SS bugprone\-easily\-swappable\-parameters
.sp
Finds function definitions where parameters of convertible types follow each
other directly, making call sites prone to calling the function with
swapped (or badly ordered) arguments.
.INDENT 0.0
.INDENT 3.5
.sp
.EX
void drawPoint(int X, int Y) { /* ... */ }
FILE *open(const char *Dir, const char *Name, Flags Mode) { /* ... */ }
.EE
.UNINDENT
.UNINDENT
.sp
A potential call like \fBdrawPoint(\-2, 5)\fP or
\fBopenPath(\(dqa.txt\(dq, \(dqtmp\(dq, Read)\fP is perfectly legal from the language\(aqs
perspective, but might not be what the developer of the function intended.
.sp
More elaborate and type\-safe constructs, such as opaque typedefs or strong
types should be used instead, to prevent a mistaken order of arguments.
.INDENT 0.0
.INDENT 3.5
.sp
.EX
struct Coord2D { int X; int Y; };
void drawPoint(const Coord2D Pos) { /* ... */ }
FILE *open(const Path &Dir, const Filename &Name, Flags Mode) { /* ... */ }
.EE
.UNINDENT
.UNINDENT
.sp
Due to the potentially elaborate refactoring and API\-breaking that is necessary
to strengthen the type safety of a project, no automatic fix\-its are offered.
.SS Options
.SS Extension/relaxation options
.sp
Relaxation (or extension) options can be used to broaden the scope of the
analysis and fine\-tune the enabling of more mixes between types.
Some mixes may depend on coding style or preference specific to a project,
however, it should be noted that enabling \fIall\fP of these relaxations model the
way of mixing at call sites the most.
These options are expected to make the check report for more functions, and
report longer mixable ranges.
.INDENT 0.0
.TP
.B QualifiersMix
Whether to consider parameters of some \fIcvr\-qualified\fP \fBT\fP and a
differently \fIcvr\-qualified\fP \fBT\fP (i.e. \fBT\fP and \fBconst T\fP, \fBconst T\fP
and \fBvolatile T\fP, etc.) mixable between one another.
If \fIfalse\fP, the check will consider differently qualified types unmixable.
\fITrue\fP turns the warnings on.
Defaults to \fIfalse\fP\&.
.sp
The following example produces a diagnostic only if \fIQualifiersMix\fP is
enabled:
.INDENT 7.0
.INDENT 3.5
.sp
.EX
void *memcpy(const void *Destination, void *Source, std::size_t N) { /* ... */ }
.EE
.UNINDENT
.UNINDENT
.UNINDENT
.INDENT 0.0
.TP
.B ModelImplicitConversions
Whether to consider parameters of type \fBT\fP and \fBU\fP mixable if there
exists an implicit conversion from \fBT\fP to \fBU\fP and \fBU\fP to \fBT\fP\&.
If \fIfalse\fP, the check will not consider implicitly convertible types for
mixability.
\fITrue\fP turns warnings for implicit conversions on.
Defaults to \fItrue\fP\&.
.sp
The following examples produce a diagnostic only if
\fIModelImplicitConversions\fP is enabled:
.INDENT 7.0
.INDENT 3.5
.sp
.EX
void fun(int Int, double Double) { /* ... */ }
void compare(const char *CharBuf, std::string String) { /* ... */ }
.EE
.UNINDENT
.UNINDENT
.sp
\fBNote:\fP
.INDENT 7.0
.INDENT 3.5
Changing the qualifiers of an expression\(aqs type (e.g. from \fBint\fP to
\fBconst int\fP) is defined as an \fIimplicit conversion\fP in the C++
Standard.
However, the check separates this decision\-making on the mixability of
differently qualified types based on whether \fIQualifiersMix\fP was
enabled.
.sp
For example, the following code snippet will only produce a diagnostic
if \fBboth\fP \fIQualifiersMix\fP and \fIModelImplicitConversions\fP are enabled:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
void fun2(int Int, const double Double) { /* ... */ }
.EE
.UNINDENT
.UNINDENT
.UNINDENT
.UNINDENT
.UNINDENT
.SS Filtering options
.sp
Filtering options can be used to lessen the size of the diagnostics emitted by
the checker, whether the aim is to ignore certain constructs or dampen the
noisiness.
.INDENT 0.0
.TP
.B MinimumLength
The minimum length required from an adjacent parameter sequence to be
diagnosed.
Defaults to \fI2\fP\&.
Might be any positive integer greater or equal to \fI2\fP\&.
If \fI0\fP or \fI1\fP is given, the default value \fI2\fP will be used instead.
.sp
For example, if \fI3\fP is specified, the examples above will not be matched.
.UNINDENT
.INDENT 0.0
.TP
.B IgnoredParameterNames
The list of parameter \fBnames\fP that should never be considered part of a
swappable adjacent parameter sequence.
The value is a \fI;\fP\-separated list of names.
To ignore unnamed parameters, add \fI\(dq\(dq\fP to the list verbatim (not the
empty string, but the two quotes, potentially escaped!).
\fBThis option is case\-sensitive!\fP
.sp
By default, the following parameter names, and their Uppercase\-initial
variants are ignored:
\fI\(dq\(dq\fP (unnamed parameters), \fIiterator\fP, \fIbegin\fP, \fIend\fP, \fIfirst\fP, \fIlast\fP,
\fIlhs\fP, \fIrhs\fP\&.
.UNINDENT
.INDENT 0.0
.TP
.B IgnoredParameterTypeSuffixes
The list of parameter \fBtype name suffixes\fP that should never be
considered part of a swappable adjacent parameter sequence.
Parameters which type, as written in the source code, end with an element
of this option will be ignored.
The value is a \fI;\fP\-separated list of names.
\fBThis option is case\-sensitive!\fP
.sp
By default, the following, and their lowercase\-initial variants are ignored:
\fIbool\fP, \fIIt\fP, \fIIterator\fP, \fIInputIt\fP, \fIForwardIt\fP, \fIBidirIt\fP, \fIRandomIt\fP,
\fIrandom_iterator\fP, \fIReverseIt\fP, \fIreverse_iterator\fP,
\fIreverse_const_iterator\fP, \fIRandomIt\fP, \fIrandom_iterator\fP, \fIReverseIt\fP,
\fIreverse_iterator\fP, \fIreverse_const_iterator\fP, \fIConst_Iterator\fP,
\fIConstIterator\fP, \fIconst_reverse_iterator\fP, \fIConstReverseIterator\fP\&.
In addition, \fI_Bool\fP (but not \fI_bool\fP) is also part of the default value.
.UNINDENT
.INDENT 0.0
.TP
.B SuppressParametersUsedTogether
Suppresses diagnostics about parameters that are used together or in a
similar fashion inside the function\(aqs body.
Defaults to \fItrue\fP\&.
Specifying \fIfalse\fP will turn off the heuristics.
.sp
Currently, the following heuristics are implemented which will suppress the
warning about the parameter pair involved:
.INDENT 7.0
.IP \(bu 2
The parameters are used in the same expression, e.g. \fBf(a, b)\fP or
\fBa < b\fP\&.
.IP \(bu 2
The parameters are further passed to the same function to the same
parameter of that function, of the same overload.
E.g. \fBf(a, 1)\fP and \fBf(b, 2)\fP to some \fBf(T, int)\fP\&.
.sp
\fBNote:\fP
.INDENT 2.0
.INDENT 3.5
The check does not perform path\-sensitive analysis, and as such,
\(dqsame function\(dq in this context means the same function declaration.
If the same member function of a type on two distinct instances are
called with the parameters, it will still be regarded as
\(dqsame function\(dq.
.UNINDENT
.UNINDENT
.IP \(bu 2
The same member field is accessed, or member method is called of the
two parameters, e.g. \fBa.foo()\fP and \fBb.foo()\fP\&.
.IP \(bu 2
Separate \fBreturn\fP statements return either of the parameters on
different code paths.
.UNINDENT
.UNINDENT
.INDENT 0.0
.TP
.B NamePrefixSuffixSilenceDissimilarityThreshold
The number of characters two parameter names might be different on \fIeither\fP
the head or the tail end with the rest of the name the same so that the
warning about the two parameters are silenced.
Defaults to \fI1\fP\&.
Might be any positive integer.
If \fI0\fP, the filtering heuristic based on the parameters\(aq names is turned
off.
.sp
This option can be used to silence warnings about parameters where the
naming scheme indicates that the order of those parameters do not matter.
.sp
For example, the parameters \fBLHS\fP and \fBRHS\fP are 1\-dissimilar suffixes
of each other: \fBL\fP and \fBR\fP is the different character, while \fBHS\fP
is the common suffix.
Similarly, parameters \fBtext1, text2, text3\fP are 1\-dissimilar prefixes
of each other, with the numbers at the end being the dissimilar part.
If the value is at least \fI1\fP, such cases will not be reported.
.UNINDENT
.SS Limitations
.sp
\fBThis check is designed to check function signatures!\fP
.sp
The check does not investigate functions that are generated by the compiler
in a context that is only determined from a call site.
These cases include variadic functions, functions in C code that do not have
an argument list, and C++ template instantiations.
Most of these cases, which are otherwise swappable from a caller\(aqs standpoint,
have no way of getting \(dqfixed\(dq at the definition point.
In the case of C++ templates, only primary template definitions and explicit
specializations are matched and analyzed.
.sp
None of the following cases produce a diagnostic:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
int printf(const char *Format, ...) { /* ... */ }
int someOldCFunction() { /* ... */ }
template
int add(T X, U Y) { return X + Y };
void theseAreNotWarnedAbout() {
printf(\(dq%d %d\en\(dq, 1, 2); // Two ints passed, they could be swapped.
someOldCFunction(1, 2, 3); // Similarly, multiple ints passed.
add(1, 2); // Instantiates \(aqadd\(aq, but that\(aqs not a user\-defined function.
}
.EE
.UNINDENT
.UNINDENT
.sp
Due to the limitation above, parameters which type are further dependent upon
template instantiations to \fIprove\fP that they mix with another parameter\(aqs is
not diagnosed.
.INDENT 0.0
.INDENT 3.5
.sp
.EX
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 \(aqT\(aq but we cannot prove this
// without actually instantiating.
template
void falseNegative(T A, typename Vector::element_type B) { /* ... */ }
.EE
.UNINDENT
.UNINDENT
.sp
In the context of \fIimplicit conversions\fP (when \fIModelImplicitConversions\fP is
enabled), the modelling performed by the check
warns if the parameters are swappable and the swapped order matches implicit
conversions.
It does not model whether there exists an unrelated third type from which
\fIboth\fP parameters can be given in a function call.
This means that in the following example, even while \fBstrs()\fP clearly carries
the possibility to be called with swapped arguments (as long as the arguments
are string literals), will not be warned about.
.INDENT 0.0
.INDENT 3.5
.sp
.EX
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() { /* ... */ }
.EE
.UNINDENT
.UNINDENT
.SS bugprone\-empty\-catch
.sp
Detects and suggests addressing issues with empty catch statements.
.INDENT 0.0
.INDENT 3.5
.sp
.EX
try {
// Some code that can throw an exception
} catch(const std::exception&) {
}
.EE
.UNINDENT
.UNINDENT
.sp
Having empty catch statements in a codebase can be a serious problem that
developers should be aware of. Catch statements are used to handle exceptions
that are thrown during program execution. When an exception is thrown, the
program jumps to the nearest catch statement that matches the type of the
exception.
.sp
Empty catch statements, also known as \(dqswallowing\(dq exceptions, catch the
exception but do nothing with it. This means that the exception is not handled
properly, and the program continues to run as if nothing happened. This can
lead to several issues, such as:
.INDENT 0.0
.IP \(bu 2
\fIHidden Bugs\fP: If an exception is caught and ignored, it can lead to hidden
bugs that are difficult to diagnose and fix. The root cause of the problem
may not be apparent, and the program may continue to behave in unexpected
ways.
.IP \(bu 2
\fISecurity Issues\fP: Ignoring exceptions can lead to security issues, such as
buffer overflows or null pointer dereferences. Hackers can exploit these
vulnerabilities to gain access to sensitive data or execute malicious code.
.IP \(bu 2
\fIPoor Code Quality\fP: Empty catch statements can indicate poor code quality
and a lack of attention to detail. This can make the codebase difficult to
maintain and update, leading to longer development cycles and increased
costs.
.IP \(bu 2
\fIUnreliable Code\fP: Code that ignores exceptions is often unreliable and can
lead to unpredictable behavior. This can cause frustration for users and
erode trust in the software.
.UNINDENT
.sp
To avoid these issues, developers should always handle exceptions properly.
This means either fixing the underlying issue that caused the exception or
propagating the exception up the call stack to a higher\-level handler.
If an exception is not important, it should still be logged or reported in
some way so that it can be tracked and addressed later.
.sp
If the exception is something that can be handled locally, then it should be
handled within the catch block. This could involve logging the exception or
taking other appropriate action to ensure that the exception is not ignored.
.sp
Here is an example:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
try {
// Some code that can throw an exception
} catch (const std::exception& ex) {
// Properly handle the exception, e.g.:
std::cerr << \(dqException caught: \(dq << ex.what() << std::endl;
}
.EE
.UNINDENT
.UNINDENT
.sp
If the exception cannot be handled locally and needs to be propagated up the
call stack, it should be re\-thrown or new exception should be thrown.
.sp
Here is an example:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
try {
// Some code that can throw an exception
} catch (const std::exception& ex) {
// Re\-throw the exception
throw;
}
.EE
.UNINDENT
.UNINDENT
.sp
In some cases, catching the exception at this level may not be necessary, and
it may be appropriate to let the exception propagate up the call stack.
This can be done simply by not using \fBtry/catch\fP block.
.sp
Here is an example:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
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 << \(dqException caught: \(dq << ex.what() << std::endl;
}
}
.EE
.UNINDENT
.UNINDENT
.sp
Other potential solution to avoid empty catch statements is to modify the code
to avoid throwing the exception in the first place. This can be achieved by
using a different API, checking for error conditions beforehand, or handling
errors in a different way that does not involve exceptions. By eliminating the
need for try\-catch blocks, the code becomes simpler and less error\-prone.
.sp
Here is an example:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
// Old code:
try {
mapContainer[\(dqKey\(dq].callFunction();
} catch(const std::out_of_range&) {
}
// New code
if (auto it = mapContainer.find(\(dqKey\(dq); it != mapContainer.end()) {
it\->second.callFunction();
}
.EE
.UNINDENT
.UNINDENT
.sp
In conclusion, empty catch statements are a bad practice that can lead to
hidden bugs, security issues, poor code quality, and unreliable code. By
handling exceptions properly, developers can ensure that their code is
robust, secure, and maintainable.
.SS Options
.INDENT 0.0
.TP
.B IgnoreCatchWithKeywords
This option can be used to ignore specific catch statements containing
certain keywords. If a \fBcatch\fP statement body contains (case\-insensitive)
any of the keywords listed in this semicolon\-separated option, then the
catch will be ignored, and no warning will be raised.
Default value: \fI@TODO;@FIXME\fP\&.
.UNINDENT
.INDENT 0.0
.TP
.B AllowEmptyCatchForExceptions
This option can be used to ignore empty catch statements for specific
exception types. By default, the check will raise a warning if an empty
catch statement is detected, regardless of the type of exception being
caught. However, in certain situations, such as when a developer wants to
intentionally ignore certain exceptions or handle them in a different way,
it may be desirable to allow empty catch statements for specific exception
types.
To configure this option, a semicolon\-separated list of exception type names
should be provided. If an exception type name in the list is caught in an
empty catch statement, no warning will be raised.
Default value: empty string.
.UNINDENT
.SS bugprone\-exception\-copy\-constructor\-throws
.sp
Checks whether a thrown object\(aqs copy constructor can throw.
.sp
Exception objects are required to be copy constructible in C++. However, an
exception\(aqs copy constructor should not throw to avoid potential issues when
unwinding the stack. If an exception is thrown during stack unwinding (such
as from a copy constructor of an exception object), the program will
terminate via \fBstd::terminate\fP\&.
.INDENT 0.0
.INDENT 3.5
.sp
.EX
class SomeException {
public:
SomeException() = default;
SomeException(const SomeException&) { /* may throw */ }
};
void f() {
throw SomeException(); // warning: thrown exception type\(aqs copy constructor can throw
}
.EE
.UNINDENT
.UNINDENT
.SS References
.sp
This check corresponds to the CERT C++ Coding Standard rule
ERR60\-CPP. Exception objects must be nothrow copy constructible \%\&.
.SS bugprone\-exception\-escape
.sp
Finds functions which may throw an exception directly or indirectly, but they
should not. The functions which should not throw exceptions are the following:
.INDENT 0.0
.IP \(bu 2
Destructors
.IP \(bu 2
Move constructors
.IP \(bu 2
Move assignment operators
.IP \(bu 2
The \fBmain()\fP functions
.IP \(bu 2
\fBswap()\fP functions
.IP \(bu 2
\fBiter_swap()\fP functions
.IP \(bu 2
\fBiter_move()\fP functions
.IP \(bu 2
Functions marked with \fBthrow()\fP or \fBnoexcept\fP
.IP \(bu 2
Other functions given as option
.UNINDENT
.sp
A destructor throwing an exception may result in undefined behavior, resource
leaks or unexpected termination of the program. Throwing move constructor or
move assignment also may result in undefined behavior or resource leak. The
\fBswap()\fP operations expected to be non throwing most of the cases and they
are always possible to implement in a non throwing way. Non throwing \fBswap()\fP
operations are also used to create move operations. A throwing \fBmain()\fP
function also results in unexpected termination.
.sp
Functions declared explicitly with \fBnoexcept(false)\fP or \fBthrow(exception)\fP
will be excluded from the analysis, as even though it is not recommended for
functions like \fBswap()\fP, \fBmain()\fP, move constructors, move assignment
operators and destructors, it is a clear indication of the developer\(aqs
intention and should be respected.
.sp
WARNING! This check may be expensive on large source files.
.SS Options
.INDENT 0.0
.TP
.B CheckDestructors
When \fItrue\fP, destructors are analyzed to not throw exceptions.
Default value is \fItrue\fP\&.
.UNINDENT
.INDENT 0.0
.TP
.B CheckMoveMemberFunctions
When \fItrue\fP, move constructors and move assignment operators are analyzed
to not throw exceptions. Default value is \fItrue\fP\&.
.UNINDENT
.INDENT 0.0
.TP
.B CheckMain
When \fItrue\fP, the \fBmain()\fP function is analyzed to not throw exceptions.
Default value is \fItrue\fP\&.
.UNINDENT
.INDENT 0.0
.TP
.B CheckNothrowFunctions
When \fItrue\fP, functions marked with \fBnoexcept\fP or \fBthrow()\fP exception
specifications are analyzed to not throw exceptions. Default value is \fItrue\fP\&.
.UNINDENT
.INDENT 0.0
.TP
.B CheckedSwapFunctions
Comma\-separated list of swap function names which should not throw exceptions.
Default value is \fIswap,iter_swap,iter_move\fP\&.
.UNINDENT
.INDENT 0.0
.TP
.B FunctionsThatShouldNotThrow
Comma separated list containing function names which should not throw. An
example value for this parameter can be \fBWinMain\fP which adds function
\fBWinMain()\fP in the Windows API to the list of the functions which should
not throw. Default value is an empty string.
.UNINDENT
.INDENT 0.0
.TP
.B IgnoredExceptions
Comma separated list containing type names which are not counted as thrown
exceptions in the check. Default value is an empty string.
.UNINDENT
.SS bugprone\-float\-loop\-counter
.sp
Flags \fBfor\fP loops where the induction expression has a floating\-point type.
.SS References
.sp
This check corresponds to the CERT C Coding Standard rule
FLP30\-C. Do not use floating\-point variables as loop counters \%\&.
.SS bugprone\-fold\-init\-type
.sp
The check flags type mismatches in
folds \%
like \fBstd::accumulate\fP that might result in loss of precision.
\fBstd::accumulate\fP folds an input range into an initial value using
the type of the latter, with \fBoperator+\fP by default. This can cause
loss of precision through:
.INDENT 0.0
.IP \(bu 2
Truncation: The following code uses a floating point range and an int
initial value, so truncation will happen at every application of
\fBoperator+\fP and the result will be \fI0\fP, which might not be what the
user expected.
.UNINDENT
.INDENT 0.0
.INDENT 3.5
.sp
.EX
auto a = {0.5f, 0.5f, 0.5f, 0.5f};
return std::accumulate(std::begin(a), std::end(a), 0);
.EE
.UNINDENT
.UNINDENT
.INDENT 0.0
.IP \(bu 2
Overflow: The following code also returns \fI0\fP\&.
.UNINDENT
.INDENT 0.0
.INDENT 3.5
.sp
.EX
auto a = {65536LL * 65536 * 65536};
return std::accumulate(std::begin(a), std::end(a), 0);
.EE
.UNINDENT
.UNINDENT
.SS bugprone\-forward\-declaration\-namespace
.sp
Checks if an unused forward declaration is in a wrong namespace.
.sp
The check inspects all unused forward declarations and checks if there is any
declaration/definition with the same name existing, which could indicate that
the forward declaration is in a potentially wrong namespace.
.INDENT 0.0
.INDENT 3.5
.sp
.EX
namespace na { struct A; }
namespace nb { struct A {}; }
nb::A a;
// warning : no definition found for \(aqA\(aq, but a definition with the same name
// \(aqA\(aq found in another namespace \(aqnb::\(aq
.EE
.UNINDENT
.UNINDENT
.sp
This check can only generate warnings, but it can\(aqt suggest a fix at this
point.
.SS bugprone\-forwarding\-reference\-overload
.sp
The check looks for perfect forwarding constructors that can hide copy or move
constructors. If a non const lvalue reference is passed to the constructor, the
forwarding reference parameter will be a better match than the const reference
parameter of the copy constructor, so the perfect forwarding constructor will
be called, which can be confusing.
For detailed description of this issue see: Scott Meyers, Effective Modern C++,
Item 26.
.sp
Consider the following example:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
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);
};
.EE
.UNINDENT
.UNINDENT
.sp
The check warns for constructors C1 and C2, because those can hide copy and
move constructors. We suppress warnings if the copy and the move constructors
are both disabled (deleted or private), because there is nothing the perfect
forwarding constructor could hide in this case. We also suppress warnings for
constructors like C3\-C6 that are guarded with an \fBenable_if\fP or a concept,
assuming the programmer was aware of the possible hiding.
.SS Background
.sp
For deciding whether a constructor is guarded with enable_if, we consider the
types of the constructor parameters, the default values of template type parameters
and the types of non\-type template parameters with a default literal value. If any
part of these types is \fBstd::enable_if\fP or \fBstd::enable_if_t\fP, we assume the
constructor is guarded.
.SS bugprone\-implicit\-widening\-of\-multiplication\-result
.sp
The check diagnoses instances where a result of a multiplication is implicitly
widened, and suggests (with fix\-it) to either silence the code by making
widening explicit, or to perform the multiplication in a wider type,
to avoid the widening afterwards.
.sp
This is mainly useful when operating on very large buffers.
For example, consider:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
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;
}
}
}
.EE
.UNINDENT
.UNINDENT
.sp
This is fine in general, but if \fBwidth * height\fP overflows,
you end up wrapping back to the beginning of \fBbase\fP
instead of processing the entire requested buffer.
.sp
Indeed, this only matters for pretty large buffers (4GB+),
but that can happen very easily for example in image processing,
where for that to happen you \(dqonly\(dq need a ~269MPix image.
.SS Options
.INDENT 0.0
.TP
.B UseCXXStaticCastsInCppSources
When suggesting fix\-its for C++ code, should C++\-style \fBstatic_cast<>()\fP\(aqs
be suggested, or C\-style casts. Defaults to \fItrue\fP\&.
.UNINDENT
.INDENT 0.0
.TP
.B UseCXXHeadersInCppSources
When suggesting to include the appropriate header in C++ code,
should \fB\fP header be suggested, or \fB\fP\&.
Defaults to \fItrue\fP\&.
.UNINDENT
.INDENT 0.0
.TP
.B IgnoreConstantIntExpr
If the multiplication operands are compile\-time constants (like literals or
are \fBconstexpr\fP) and fit within the source expression type, do not emit a
diagnostic or suggested fix. Only considers expressions where the source
expression is a signed integer type. Defaults to \fIfalse\fP\&.
.UNINDENT
.sp
Examples:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
long mul(int a, int b) {
return a * b; // warning: performing an implicit widening conversion to type \(aqlong\(aq of a multiplication performed in type \(aqint\(aq
}
char* ptr_add(char *base, int a, int b) {
return base + a * b; // warning: result of multiplication in type \(aqint\(aq is used as a pointer offset after an implicit widening conversion to type \(aqssize_t\(aq
}
char ptr_subscript(char *base, int a, int b) {
return base[a * b]; // warning: result of multiplication in type \(aqint\(aq is used as a pointer offset after an implicit widening conversion to type \(aqssize_t\(aq
}
.EE
.UNINDENT
.UNINDENT
.SS bugprone\-inaccurate\-erase
.sp
Checks for inaccurate use of the \fBerase()\fP method.
.sp
Algorithms like \fBremove()\fP do not actually remove any element from the
container but return an iterator to the first redundant element at the end
of the container. These redundant elements must be removed using the
\fBerase()\fP method. This check warns when not all of the elements will be
removed due to using an inappropriate overload.
.sp
For example, the following code erases only one element:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
std::vector xs;
\&...
xs.erase(std::remove(xs.begin(), xs.end(), 10));
.EE
.UNINDENT
.UNINDENT
.sp
Call the two\-argument overload of \fBerase()\fP to remove the subrange:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
std::vector xs;
\&...
xs.erase(std::remove(xs.begin(), xs.end(), 10), xs.end());
.EE
.UNINDENT
.UNINDENT
.SS bugprone\-inc\-dec\-in\-conditions
.sp
Detects when a variable is both incremented/decremented and referenced inside a
complex condition and suggests moving them outside to avoid ambiguity in the
variable\(aqs value.
.sp
When a variable is modified and also used in a complex condition, it can lead
to unexpected behavior. The side\-effect of changing the variable\(aqs value within
the condition can make the code difficult to reason about. Additionally, the
developer\(aqs intended timing for the modification of the variable may not be
clear, leading to misunderstandings and errors. This can be particularly
problematic when the condition involves logical operators like \fB&&\fP and
\fB||\fP, where the order of evaluation can further complicate the situation.
.sp
Consider the following example:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
int i = 0;
// ...
if (i++ < 5 && i > 0) {
// do something
}
.EE
.UNINDENT
.UNINDENT
.sp
In this example, the result of the expression may not be what the developer
intended. The original intention of the developer could be to increment \fBi\fP
after the entire condition is evaluated, but in reality, i will be incremented
before \fBi > 0\fP is executed. This can lead to unexpected behavior and bugs in
the code. To fix this issue, the developer should separate the increment
operation from the condition and perform it separately. For example, they can
increment \fBi\fP in a separate statement before or after the condition is
evaluated. This ensures that the value of \fBi\fP is predictable and consistent
throughout the code.
.INDENT 0.0
.INDENT 3.5
.sp
.EX
int i = 0;
// ...
i++;
if (i <= 5 && i > 0) {
// do something
}
.EE
.UNINDENT
.UNINDENT
.sp
Another common issue occurs when multiple increments or decrements are
performed on the same variable inside a complex condition. For example:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
int i = 4;
// ...
if (i++ < 5 || \-\-i > 2) {
// do something
}
.EE
.UNINDENT
.UNINDENT
.sp
There is a potential issue with this code due to the order of evaluation in
C++. The \fB||\fP operator used in the condition statement guarantees that if
the first operand evaluates to \fBtrue\fP, the second operand will not be
evaluated. This means that if \fBi\fP were initially \fB4\fP, the first operand
\fBi < 5\fP would evaluate to \fBtrue\fP and the second operand \fBi > 2\fP would
not be evaluated. As a result, the decrement operation \fB\-\-i\fP would not be
executed and \fBi\fP would hold value \fB5\fP, which may not be the intended
behavior for the developer.
.sp
To avoid this potential issue, the both increment and decrement operation on
\fBi\fP should be moved outside the condition statement.
.SS bugprone\-incorrect\-enable\-if
.sp
Detects incorrect usages of \fBstd::enable_if\fP that don\(aqt name the nested
\fBtype\fP type.
.sp
In C++11 introduced \fBstd::enable_if\fP as a convenient way to leverage SFINAE.
One form of using \fBstd::enable_if\fP is to declare an unnamed template type
parameter with a default type equal to
\fBtypename std::enable_if::type\fP\&. If the author forgets to name
the nested type \fBtype\fP, then the code will always consider the candidate
template even if the condition is not met.
.sp
Below are some examples of code using \fBstd::enable_if\fP correctly and
incorrect examples that this check flags.
.INDENT 0.0
.INDENT 3.5
.sp
.EX
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 \(aqinvalid_usage\(aq:
template ::type>
void fixed_invalid_usage() { ... }
.EE
.UNINDENT
.UNINDENT
.sp
C++14 introduced the trait helper \fBstd::enable_if_t\fP which reduces the
likelihood of this error. C++20 introduces constraints, which generally
supersede the use of \fBstd::enable_if\fP\&. See
modernize\-type\-traits \%<> for another tool
that will replace \fBstd::enable_if\fP with
\fBstd::enable_if_t\fP, and see
modernize\-use\-constraints \%<> for another
tool that replaces \fBstd::enable_if\fP with C++20 constraints. Consider these
newer mechanisms where possible.
.SS bugprone\-incorrect\-enable\-shared\-from\-this
.sp
Detect classes or structs that do not publicly inherit from
\fBstd::enable_shared_from_this\fP, because unintended behavior will
otherwise occur when calling \fBshared_from_this\fP\&.
.sp
Consider the following code:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
#include
// private inheritance
class BadExample : std::enable_shared_from_this {
// \(ga\(gashared_from_this\(ga\(ga\(ga unintended behaviour
// \(galibstdc++\(ga implementation returns uninitialized \(ga\(gaweak_ptr\(ga\(ga
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();
}
.EE
.UNINDENT
.UNINDENT
.sp
Using \fIlibstdc++\fP implementation, \fBshared_from_this\fP will throw
\fBstd::bad_weak_ptr\fP\&. When \fBusing_not_public()\fP is called, this code will
crash without exception handling.
.SS bugprone\-incorrect\-roundings
.sp
Checks the usage of patterns known to produce incorrect rounding.
Programmers often use:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
(int)(double_expression + 0.5)
.EE
.UNINDENT
.UNINDENT
.sp
to round the double expression to an integer. The problem with this:
.INDENT 0.0
.IP 1. 3
It is unnecessarily slow.
.IP 2. 3
It is incorrect. The number 0.499999975 (smallest representable float
number below 0.5) rounds to 1.0. Even worse behavior for negative
numbers where both \-0.5f and \-1.4f both round to 0.0.
.UNINDENT
.SS bugprone\-infinite\-loop
.sp
Finds obvious infinite loops (loops where the condition variable is not changed
at all).
.sp
Finding infinite loops is well\-known to be impossible (halting problem).
However, it is possible to detect some obvious infinite loops, for example, if
the loop condition is not changed. This check detects such loops. A loop is
considered infinite if it does not have any loop exit statement (\fBbreak\fP,
\fBcontinue\fP, \fBgoto\fP, \fBreturn\fP, \fBthrow\fP or a call to a function called as
\fB[[noreturn]]\fP) and all of the following conditions hold for every variable
in the condition:
.INDENT 0.0
.IP \(bu 2
It is a local variable.
.IP \(bu 2
It has no reference or pointer aliases.
.IP \(bu 2
It is not a structure or class member.
.UNINDENT
.sp
Furthermore, the condition must not contain a function call to consider the
loop infinite since functions may return different values for different calls.
.sp
For example, the following loop is considered infinite \fIi\fP is not changed in
the body:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
int i = 0, j = 0;
while (i < 10) {
++j;
}
.EE
.UNINDENT
.UNINDENT
.SS bugprone\-integer\-division
.sp
Finds cases where integer division in a floating point context is likely to
cause unintended loss of precision.
.sp
No reports are made if divisions are part of the following expressions:
.INDENT 0.0
.IP \(bu 2
operands of operators expecting integral or bool types,
.IP \(bu 2
call expressions of integral or bool types, and
.IP \(bu 2
explicit cast expressions to integral or bool types,
.UNINDENT
.sp
as these are interpreted as signs of deliberateness from the programmer.
.sp
Examples:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
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;
.EE
.UNINDENT
.UNINDENT
.SS bugprone\-invalid\-enum\-default\-initialization
.sp
Detects default initialization (to 0) of variables with \fBenum\fP type where
the enum has no enumerator with value of 0.
.sp
In C++ a default initialization is performed if a variable is initialized with
initializer list or in other implicit ways, and no value is specified at the
initialization. In such cases the value 0 is used for the initialization.
This also applies to enumerations even if it does not have an enumerator with
value 0. In this way a variable with the \fBenum\fP type may contain initially an
invalid value (if the program expects that it contains only the listed
enumerator values).
.sp
The check emits a warning only if an \fBenum\fP variable is default\-initialized
(contrary to not initialized) and the \fBenum\fP does not have an enumerator with
value of 0. The type can be a scoped or non\-scoped \fBenum\fP\&. Unions are not
handled by the check (if it contains a member of enumeration type).
.sp
Note that the \fBenum\fP \fBstd::errc\fP is always ignored because it is expected
to be default initialized, despite not defining an enumerator with the value 0.
.INDENT 0.0
.INDENT 3.5
.sp
.EX
enum class Enum1: int {
A = 1,
B
};
enum class Enum0: int {
A = 0,
B
};
void f() {
Enum1 X1{}; // warn: \(aqX1\(aq is initialized to 0
Enum1 X2 = Enum1(); // warn: \(aqX2\(aq is initialized to 0
Enum1 X3; // no warning: \(aqX3\(aq is not initialized
Enum0 X4{}; // no warning: type has an enumerator with value of 0
}
struct S1 {
Enum1 A;
S(): A() {} // warn: \(aqA\(aq is initialized to 0
};
struct S2 {
int A;
Enum1 B;
};
S2 VarS2{}; // warn: member \(aqB\(aq is initialized to 0
.EE
.UNINDENT
.UNINDENT
.sp
The check applies to initialization of arrays or structures with initialization
lists in C code too. In these cases elements not specified in the list (and have
enum type) are set to 0.
.INDENT 0.0
.INDENT 3.5
.sp
.EX
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 \(aqb\(aq is initialized to 0
.EE
.UNINDENT
.UNINDENT
.SS Options
.INDENT 0.0
.TP
.B IgnoredEnums
Semicolon\-separated list of regexes specifying enums for which this check won\(aqt be
enforced. Default is \fI::std::errc\fP\&.
.UNINDENT
.SS bugprone\-lambda\-function\-name
.sp
Checks for attempts to get the name of a function from within a lambda
expression. The name of a lambda is always something like \fBoperator()\fP, which
is almost never what was intended.
.sp
Example:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
void FancyFunction() {
[] { printf(\(dqCalled from %s\en\(dq, __func__); }();
[] { printf(\(dqNow called from %s\en\(dq, __FUNCTION__); }();
}
.EE
.UNINDENT
.UNINDENT
.sp
Output:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
Called from operator()
Now called from operator()
.EE
.UNINDENT
.UNINDENT
.sp
Likely intended output:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
Called from FancyFunction
Now called from FancyFunction
.EE
.UNINDENT
.UNINDENT
.SS Options
.INDENT 0.0
.TP
.B IgnoreMacros
The value \fItrue\fP specifies that attempting to get the name of a function from
within a macro should not be diagnosed. The default value is \fIfalse\fP\&.
.UNINDENT
.SS bugprone\-macro\-parentheses
.sp
Finds macros that can have unexpected behavior due to missing parentheses.
.sp
Macros are expanded by the preprocessor as\-is. As a result, there can be
unexpected behavior; operators may be evaluated in unexpected order and
unary operators may become binary operators, etc.
.sp
When the replacement list has an expression, it is recommended to surround
it with parentheses. This ensures that the macro result is evaluated
completely before it is used.
.sp
It is also recommended to surround macro arguments in the replacement list
with parentheses. This ensures that the argument value is calculated
properly.
.sp
This check corresponds to the CERT C Coding Standard rule
PRE02\-C. Macro replacement lists should be parenthesized. \%
.SS bugprone\-macro\-repeated\-side\-effects
.sp
Checks for repeated argument with side effects in macros.
.SS bugprone\-misleading\-setter\-of\-reference
.sp
Finds setter\-like member functions that take a pointer parameter and set a
reference member of the same class with the pointed value.
.sp
The check detects member functions that take a single pointer parameter,
and contain a single expression statement that dereferences the parameter and
assigns the result to a data member with a reference type.
.sp
The fact that a setter function takes a pointer might cause the belief that an
internal reference (if it would be a pointer) is changed instead of the
pointed\-to (or referenced) value.
.sp
Example:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
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);
}
.EE
.UNINDENT
.UNINDENT
.INDENT 0.0
.TP
.B Possible fixes:
.INDENT 7.0
.IP \(bu 2
Change the parameter type of the \(dqset\(dq function to non\-pointer type (for
example, a const reference).
.IP \(bu 2
Change the type of the member variable to a pointer and in the \(dqset\(dq
function assign a value to the pointer (without dereference).
.UNINDENT
.UNINDENT
.SS bugprone\-misplaced\-operator\-in\-strlen\-in\-alloc
.sp
Finds cases where \fB1\fP is added to the string in the argument to \fBstrlen()\fP,
\fBstrnlen()\fP, \fBstrnlen_s()\fP, \fBwcslen()\fP, \fBwcsnlen()\fP, and
\fBwcsnlen_s()\fP instead of the result and the value is used as an argument to a
memory allocation function (\fBmalloc()\fP, \fBcalloc()\fP, \fBrealloc()\fP,
\fBalloca()\fP) or the \fBnew[]\fP operator in \fIC++\fP\&. The check detects error cases
even if one of these functions (except the \fBnew[]\fP operator) is called by a
constant function pointer. Cases where \fB1\fP is added both to the parameter and
the result of the \fBstrlen()\fP\-like function are ignored, as are cases where
the whole addition is surrounded by extra parentheses.
.sp
\fIC\fP example code:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
void bad_malloc(char *str) {
char *c = (char*) malloc(strlen(str + 1));
}
.EE
.UNINDENT
.UNINDENT
.sp
The suggested fix is to add \fB1\fP to the return value of \fBstrlen()\fP and not
to its argument. In the example above the fix would be
.INDENT 0.0
.INDENT 3.5
.sp
.EX
char *c = (char*) malloc(strlen(str) + 1);
.EE
.UNINDENT
.UNINDENT
.sp
\fIC++\fP example code:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
void bad_new(char *str) {
char *c = new char[strlen(str + 1)];
}
.EE
.UNINDENT
.UNINDENT
.sp
As in the \fIC\fP code with the \fBmalloc()\fP function, the suggested fix is to
add \fB1\fP to the return value of \fBstrlen()\fP and not to its argument. In the
example above the fix would be
.INDENT 0.0
.INDENT 3.5
.sp
.EX
char *c = new char[strlen(str) + 1];
.EE
.UNINDENT
.UNINDENT
.sp
Example for silencing the diagnostic:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
void bad_malloc(char *str) {
char *c = (char*) malloc(strlen((str + 1)));
}
.EE
.UNINDENT
.UNINDENT
.SS bugprone\-misplaced\-pointer\-arithmetic\-in\-alloc
.sp
Finds cases where an integer expression is added to or subtracted from the
result of a memory allocation function (\fBmalloc()\fP, \fBcalloc()\fP,
\fBrealloc()\fP, \fBalloca()\fP) instead of its argument. The check detects error
cases even if one of these functions is called by a constant function pointer.
.sp
Example code:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
void bad_malloc(int n) {
char *p = (char*) malloc(n) + 10;
}
.EE
.UNINDENT
.UNINDENT
.sp
The suggested fix is to add the integer expression to the argument of
\fBmalloc\fP and not to its result. In the example above the fix would be
.INDENT 0.0
.INDENT 3.5
.sp
.EX
char *p = (char*) malloc(n + 10);
.EE
.UNINDENT
.UNINDENT
.SS bugprone\-misplaced\-widening\-cast
.sp
This check will warn when there is a cast of a calculation result to a bigger
type. If the intention of the cast is to avoid loss of precision then the cast
is misplaced, and there can be loss of precision. Otherwise the cast is
ineffective.
.sp
Example code:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
long f(int x) {
return (long)(x * 1000);
}
.EE
.UNINDENT
.UNINDENT
.sp
The result \fBx * 1000\fP is first calculated using \fBint\fP precision. If the
result exceeds \fBint\fP precision there is loss of precision. Then the result is
casted to \fBlong\fP\&.
.sp
If there is no loss of precision then the cast can be removed or you can
explicitly cast to \fBint\fP instead.
.sp
If you want to avoid loss of precision then put the cast in a proper location,
for instance:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
long f(int x) {
return (long)x * 1000;
}
.EE
.UNINDENT
.UNINDENT
.SS Implicit casts
.sp
Forgetting to place the cast at all is at least as dangerous and at least as
common as misplacing it. If \fBCheckImplicitCasts\fP is enabled the check
also detects these cases, for instance:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
long f(int x) {
return x * 1000;
}
.EE
.UNINDENT
.UNINDENT
.SS Floating point
.sp
Currently warnings are only written for integer conversion. No warning is
written for this code:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
double f(float x) {
return (double)(x * 10.0f);
}
.EE
.UNINDENT
.UNINDENT
.SS Options
.INDENT 0.0
.TP
.B CheckImplicitCasts
If \fItrue\fP, enables detection of implicit casts. Default is \fIfalse\fP\&.
.UNINDENT
.SS bugprone\-move\-forwarding\-reference
.sp
Warns if \fBstd::move\fP is called on a forwarding reference, for example:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
template
void foo(T&& t) {
bar(std::move(t));
}
.EE
.UNINDENT
.UNINDENT
.sp
Forwarding references \% should
typically be passed to \fBstd::forward\fP instead of \fBstd::move\fP, and this is
the fix that will be suggested.
.sp
(A forwarding reference is an rvalue reference of a type that is a deduced
function template argument.)
.sp
In this example, the suggested fix would be
.INDENT 0.0
.INDENT 3.5
.sp
.EX
bar(std::forward(t));
.EE
.UNINDENT
.UNINDENT
.SS Background
.sp
Code like the example above is sometimes written with the expectation that
\fBT&&\fP will always end up being an rvalue reference, no matter what type is
deduced for \fBT\fP, and that it is therefore not possible to pass an lvalue to
\fBfoo()\fP\&. However, this is not true. Consider this example:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
std::string s = \(dqHello, world\(dq;
foo(s);
.EE
.UNINDENT
.UNINDENT
.sp
This code compiles and, after the call to \fBfoo()\fP, \fBs\fP is left in an
indeterminate state because it has been moved from. This may be surprising to
the caller of \fBfoo()\fP because no \fBstd::move\fP was used when calling
\fBfoo()\fP\&.
.sp
The reason for this behavior lies in the special rule for template argument
deduction on function templates like \fBfoo()\fP \-\- i.e. on function templates
that take an rvalue reference argument of a type that is a deduced function
template argument. (See section [temp.deduct.call]/3 in the C++11 standard.)
.sp
If \fBfoo()\fP is called on an lvalue (as in the example above), then \fBT\fP is
deduced to be an lvalue reference. In the example, \fBT\fP is deduced to be
\fBstd::string &\fP\&. The type of the argument \fBt\fP therefore becomes
\fBstd::string& &&\fP; by the reference collapsing rules, this collapses to
\fBstd::string&\fP\&.
.sp
This means that the \fBfoo(s)\fP call passes \fBs\fP as an lvalue reference, and
\fBfoo()\fP ends up moving \fBs\fP and thereby placing it into an indeterminate
state.
.SS bugprone\-multi\-level\-implicit\-pointer\-conversion
.sp
Detects implicit conversions between pointers of different levels of
indirection.
.sp
Conversions between pointer types of different levels of indirection can be
dangerous and may lead to undefined behavior, particularly if the converted
pointer is later cast to a type with a different level of indirection.
For example, converting a pointer to a pointer to an \fBint\fP (\fBint**\fP) to
a \fBvoid*\fP can result in the loss of information about the original level of
indirection, which can cause problems when attempting to use the converted
pointer. If the converted pointer is later cast to a type with a different
level of indirection and dereferenced, it may lead to access violations,
memory corruption, or other undefined behavior.
.sp
Consider the following example:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
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;
}
.EE
.UNINDENT
.UNINDENT
.sp
In this example, \fBfoo()\fP is called with \fBptr_ptr\fP as its argument. However,
\fBptr_ptr\fP is a \fBint**\fP pointer, while \fBfoo()\fP expects a \fBvoid*\fP pointer.
This results in an implicit pointer level conversion, which could cause issues
if \fBfoo()\fP dereferences the pointer assuming it\(aqs a \fBint*\fP pointer.
.sp
Using an explicit cast is a recommended solution to prevent issues caused by
implicit pointer level conversion, as it allows the developer to explicitly
state their intention and show their reasoning for the type conversion.
Additionally, it is recommended that developers thoroughly check and verify the
safety of the conversion before using an explicit cast. This extra level of
caution can help catch potential issues early on in the development process,
improving the overall reliability and maintainability of the code.
.SS Options
.INDENT 0.0
.TP
.B EnableInC
If \fItrue\fP, enables the check in C code (it is always enabled in C++ code).
Default is \fItrue\fP\&.
.UNINDENT
.SS bugprone\-multiple\-new\-in\-one\-expression
.sp
Finds multiple \fBnew\fP operator calls in a single expression, where the
allocated memory by the first \fBnew\fP may leak if the second allocation fails
and throws exception.
.sp
C++ does often not specify the exact order of evaluation of the operands of an
operator or arguments of a function. Therefore if a first allocation succeeds
and a second fails, in an exception handler it is not possible to tell which
allocation has failed and free the memory. Even if the order is fixed the
result of a first \fBnew\fP may be stored in a temporary location that is not
reachable at the time when a second allocation fails. It is best to avoid any
expression that contains more than one \fBoperator new\fP call, if exception
handling is used to check for allocation errors.
.sp
Different rules apply for are the short\-circuit operators \fB||\fP and \fB&&\fP and
the \fB,\fP operator, where evaluation of one side must be completed before the
other starts. Expressions of a list\-initialization (initialization or
construction using \fB{\fP and \fB}\fP characters) are evaluated in fixed order.
Similarly, condition of a \fB?\fP operator is evaluated before the branches are
evaluated.
.sp
The check reports warning if two \fBnew\fP calls appear in one expression at
different sides of an operator, or if \fBnew\fP calls appear in different
arguments of a function call (that can be an object construction with \fB()\fP
syntax). These \fBnew\fP calls can be nested at any level.
For any warning to be emitted the \fBnew\fP calls should be in a code block where
exception handling is used with catch for \fBstd::bad_alloc\fP or
\fBstd::exception\fP\&. At \fB||\fP, \fB&&\fP, \fB,\fP, \fB?\fP (condition and one branch)
operators no warning is emitted. No warning is emitted if both of the memory
allocations are not assigned to a variable or not passed directly to a
function. The reason is that in this case the memory may be intentionally not
freed or the allocated objects can be self\-destructing objects.
.sp
Examples:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
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 \(aqB\(aq/\(aqA\(aq may fail after memory for \(aqA\(aq/\(aqB\(aq 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 \(aqB\(aq/\(aqA\(aq may fail after memory for \(aqA\(aq/\(aqB\(aq was allocated but not yet passed to function \(aqf1\(aq.
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 \(aqB\(aq may fail after memory for \(aqA\(aq was allocated.
// From C++17 on memory for \(aqB\(aq is allocated first but still may leak if allocation of \(aqA\(aq fails.
PtrB = new B(new A); // warning: memory allocation may leak if an other allocation is sequenced after it and throws an exception
// \(aqnew A\(aq and \(aqnew B\(aq may be performed in any order.
// \(aqnew B\(aq/\(aqnew A\(aq may fail after memory for \(aqA\(aq/\(aqB\(aq was allocated but not assigned to \(aqPtrA\(aq/\(aqPtrB\(aq.
(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 \(aqf2(new A)\(aq must be finished before \(aqf1(new B)\(aq starts.
// If \(aqnew B\(aq fails the allocated memory for \(aqA\(aq is supposedly handled correctly because function \(aqf2\(aq 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 \(aqfoo\(aq is not taken into account.)
f(new A, new B); // no warning
}
.EE
.UNINDENT
.UNINDENT
.SS bugprone\-multiple\-statement\-macro
.sp
Detect multiple statement macros that are used in unbraced conditionals. Only
the first statement of the macro will be inside the conditional and the other
ones will be executed unconditionally.
.sp
Example:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
#define INCREMENT_TWO(x, y) (x)++; (y)++
if (do_increment)
INCREMENT_TWO(a, b); // (b)++ will be executed unconditionally.
.EE
.UNINDENT
.UNINDENT
.SS bugprone\-narrowing\-conversions
.sp
\fIcppcoreguidelines\-narrowing\-conversions\fP redirects here as an alias for
this check.
.sp
Checks for silent narrowing conversions, e.g: \fBint i = 0; i += 0.1;\fP\&. While
the issue is obvious in this former example, it might not be so in the
following: \fBvoid MyClass::f(double d) { int_member_ += d; }\fP\&.
.INDENT 0.0
.TP
.B We flag narrowing conversions from:
.INDENT 7.0
.IP \(bu 2
an integer to a narrower integer (e.g. \fBchar\fP to \fBunsigned char\fP)
if WarnOnIntegerNarrowingConversion Option is set,
.IP \(bu 2
an integer to a narrower floating\-point (e.g. \fBuint64_t\fP to \fBfloat\fP)
if WarnOnIntegerToFloatingPointNarrowingConversion Option is set,
.IP \(bu 2
a floating\-point to an integer (e.g. \fBdouble\fP to \fBint\fP),
.IP \(bu 2
a floating\-point to a narrower floating\-point (e.g. \fBdouble\fP to \fBfloat\fP)
if WarnOnFloatingPointNarrowingConversion Option is set.
.UNINDENT
.TP
.B This check will flag:
.INDENT 7.0
.IP \(bu 2
All narrowing conversions that are not marked by an explicit cast (c\-style
or \fBstatic_cast\fP). For example: \fBint i = 0; i += 0.1;\fP,
\fBvoid f(int); f(0.1);\fP,
.IP \(bu 2
All applications of binary operators with a narrowing conversions.
For example: \fBint i; i+= 0.1;\fP\&.
.UNINDENT
.UNINDENT
.sp
Arithmetic with smaller integer types than \fBint\fP trigger implicit conversions,
as explained under \(dqIntegral Promotion\(dq on cppreference.com \%\&.
This check diagnoses more instances of narrowing than the compiler warning
\fI\-Wconversion\fP does. The example below demonstrates this behavior.
.INDENT 0.0
.INDENT 3.5
.sp
.EX
// The following function definition demonstrates usage of arithmetic with
// integer types smaller than \(gaint\(ga 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 \(aqint\(aq to signed type \(aqshort\(aq 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 \(gastatic_cast\(ga will silence the warning as well if the GSL
// is not available.
short result = static_cast(argument1 + argument2);
}
.EE
.UNINDENT
.UNINDENT
.SS Options
.INDENT 0.0
.TP
.B WarnOnIntegerNarrowingConversion
When \fItrue\fP, the check will warn on narrowing integer conversion
(e.g. \fBint\fP to \fBsize_t\fP). \fItrue\fP by default.
.UNINDENT
.INDENT 0.0
.TP
.B WarnOnIntegerToFloatingPointNarrowingConversion
When \fItrue\fP, the check will warn on narrowing integer to floating\-point
conversion (e.g. \fBsize_t\fP to \fBdouble\fP). \fItrue\fP by default.
.UNINDENT
.INDENT 0.0
.TP
.B WarnOnFloatingPointNarrowingConversion
When \fItrue\fP, the check will warn on narrowing floating point conversion
(e.g. \fBdouble\fP to \fBfloat\fP). \fItrue\fP by default.
.UNINDENT
.INDENT 0.0
.TP
.B WarnWithinTemplateInstantiation
When \fItrue\fP, the check will warn on narrowing conversions within template
instantiations. \fIfalse\fP by default.
.UNINDENT
.INDENT 0.0
.TP
.B WarnOnEquivalentBitWidth
When \fItrue\fP, the check will warn on narrowing conversions that arise from
casting between types of equivalent bit width. (e.g.
\fIint n = uint(0);\fP or \fIlong long n = double(0);\fP) \fItrue\fP by default.
.UNINDENT
.INDENT 0.0
.TP
.B IgnoreConversionFromTypes
Narrowing conversions from any type in this semicolon\-separated list will be
ignored. This may be useful to weed out commonly occurring, but less commonly
problematic assignments such as \fIint n = std::vector().size();\fP or
\fIint n = std::difference(it1, it2);\fP\&. The default list is empty, but one
suggested list for a legacy codebase would be
\fIsize_t;ptrdiff_t;size_type;difference_type\fP\&.
.UNINDENT
.INDENT 0.0
.TP
.B PedanticMode
When \fItrue\fP, the check will warn on assigning a floating point constant
to an integer value even if the floating point value is exactly
representable in the destination type (e.g. \fBint i = 1.0;\fP).
\fIfalse\fP by default.
.UNINDENT
.SS FAQ
.INDENT 0.0
.INDENT 3.5
.INDENT 0.0
.IP \(bu 2
What does \(dqnarrowing conversion from \(aqint\(aq to \(aqfloat\(aq\(dq mean?
.UNINDENT
.UNINDENT
.UNINDENT
.sp
An IEEE754 Floating Point number can represent all integer values in the range
[\-2^PrecisionBits, 2^PrecisionBits] where PrecisionBits is the number of bits
in the mantissa.
.sp
For \fBfloat\fP this would be [\-2^23, 2^23], where \fBint\fP can represent values
in the range [\-2^31, 2^31\-1].
.INDENT 0.0
.INDENT 3.5
.INDENT 0.0
.IP \(bu 2
What does \(dqimplementation\-defined\(dq mean?
.UNINDENT
.UNINDENT
.UNINDENT
.sp
You may have encountered messages like \(dqnarrowing conversion from \(aqunsigned
int\(aq to signed type \(aqint\(aq is implementation\-defined\(dq.
The C/C++ standard does not mandate two\(aqs complement for signed integers, and
so the compiler is free to define what the semantics are for converting an
unsigned integer to signed integer. Clang\(aqs implementation uses the two\(aqs
complement format.
.SS bugprone\-no\-escape
.sp
Finds pointers with the \fBnoescape\fP attribute that are captured by an
asynchronously\-executed block. The block arguments in \fBdispatch_async()\fP and
\fBdispatch_after()\fP are guaranteed to escape, so it is an error if a pointer
with the \fBnoescape\fP attribute is captured by one of these blocks.
.sp
The following is an example of an invalid use of the \fBnoescape\fP attribute.
.INDENT 0.0
.INDENT 3.5
.INDENT 0.0
.INDENT 3.5
.sp
.EX
void foo(__attribute__((noescape)) int *p) {
dispatch_async(queue, ^{
*p = 123;
});
});
.EE
.UNINDENT
.UNINDENT
.UNINDENT
.UNINDENT
.SS bugprone\-non\-zero\-enum\-to\-bool\-conversion
.sp
Detect implicit and explicit casts of \fBenum\fP type into \fBbool\fP where
\fBenum\fP type doesn\(aqt have a zero\-value enumerator. If the \fBenum\fP is used
only to hold values equal to its enumerators, then conversion to \fBbool\fP will
always result in \fBtrue\fP value. This can lead to unnecessary code that reduces
readability and maintainability and can result in bugs.
.sp
May produce false positives if the \fBenum\fP is used to store other values
(used as a bit\-mask or zero\-initialized on purpose). To deal with them,
\fB// NOLINT\fP or casting first to the underlying type before casting to
\fBbool\fP can be used.
.sp
It is important to note that this check will not generate warnings if the
definition of the enumeration type is not available.
Additionally, C++11 enumeration classes are supported by this check.
.sp
Overall, this check serves to improve code quality and readability by
identifying and flagging instances where implicit or explicit casts from
enumeration types to boolean could cause potential issues.
.SS Example
.INDENT 0.0
.INDENT 3.5
.sp
.EX
enum EStatus {
OK = 1,
NOT_OK,
UNKNOWN
};
void process(EStatus status) {
if (!status) {
// this true\-branch won\(aqt be executed
return;
}
// proceed with \(dqvalid data\(dq
}
.EE
.UNINDENT
.UNINDENT
.SS Options
.INDENT 0.0
.TP
.B EnumIgnoreList
Option is used to ignore certain enum types when checking for
implicit/explicit casts to bool. It accepts a semicolon\-separated list of
(fully qualified) enum type names or regular expressions that match the enum
type names.
The default value is an empty string, which means no enums will be ignored.
.UNINDENT
.SS bugprone\-nondeterministic\-pointer\-iteration\-order
.sp
Finds nondeterministic usages of pointers in unordered containers.
.sp
One canonical example is iteration across a container of pointers.
.INDENT 0.0
.INDENT 3.5
.sp
.EX
{
int a = 1, b = 2;
std::unordered_set UnorderedPtrSet = {&a, &b};
for (auto i : UnorderedPtrSet)
f(i);
}
.EE
.UNINDENT
.UNINDENT
.sp
Another such example is sorting a container of pointers.
.INDENT 0.0
.INDENT 3.5
.sp
.EX
{
int a = 1, b = 2;
std::vector VectorOfPtr = {&a, &b};
std::sort(VectorOfPtr.begin(), VectorOfPtr.end());
}
.EE
.UNINDENT
.UNINDENT
.sp
Iteration of a containers of pointers may present the order of different
pointers differently across different runs of a program. In some cases this
may be acceptable behavior, in others this may be unexpected behavior. This
check is advisory for this reason.
.sp
This check only detects range\-based for loops over unordered sets and maps. It
also detects calls sorting\-like algorithms on containers holding pointers.
Other similar usages will not be found and are false negatives.
.SS Limitations
.INDENT 0.0
.IP \(bu 2
This check currently does not check if a nondeterministic iteration order is
likely to be a mistake, and instead marks all such iterations as bugprone.
.IP \(bu 2
std::reference_wrapper is not considered yet.
.IP \(bu 2
Only for loops are considered, other iterators can be included in
improvements.
.UNINDENT
.SS bugprone\-not\-null\-terminated\-result
.sp
Finds function calls where it is possible to cause a not null\-terminated
result. Usually the proper length of a string is \fBstrlen(src) + 1\fP or equal
length of this expression, because the null terminator needs an extra space.
Without the null terminator it can result in undefined behavior when the
string is read.
.sp
The following and their respective \fBwchar_t\fP based functions are checked:
.sp
\fBmemcpy\fP, \fBmemcpy_s\fP, \fBmemchr\fP, \fBmemmove\fP, \fBmemmove_s\fP,
\fBstrerror_s\fP, \fBstrncmp\fP, \fBstrxfrm\fP
.sp
The following is a real\-world example where the programmer forgot to increase
the passed third argument, which is \fBsize_t length\fP\&. That is why the length
of the allocated memory is not enough to hold the null terminator.
.INDENT 0.0
.INDENT 3.5
.sp
.EX
static char *stringCpy(const std::string &str) {
char *result = reinterpret_cast(malloc(str.size()));
memcpy(result, str.data(), str.size());
return result;
}
.EE
.UNINDENT
.UNINDENT
.sp
In addition to issuing warnings, fix\-it rewrites all the necessary code.
It also tries to adjust the capacity of the destination array:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
static char *stringCpy(const std::string &str) {
char *result = reinterpret_cast(malloc(str.size() + 1));
strcpy(result, str.data());
return result;
}
.EE
.UNINDENT
.UNINDENT
.sp
Note: It cannot guarantee to rewrite every of the path\-sensitive memory
allocations.
.SS Transformation rules of \(aqmemcpy()\(aq
.sp
It is possible to rewrite the \fBmemcpy()\fP and \fBmemcpy_s()\fP calls as the
following four functions: \fBstrcpy()\fP, \fBstrncpy()\fP, \fBstrcpy_s()\fP,
\fBstrncpy_s()\fP, where the latter two are the safer versions of the former two.
It rewrites the \fBwchar_t\fP based memory handler functions respectively.
.SS Rewrite based on the destination array
.INDENT 0.0
.IP \(bu 2
If copy to the destination array cannot overflow [1] the new function should
be the older copy function (ending with \fBcpy\fP), because it is more
efficient than the safe version.
.IP \(bu 2
If copy to the destination array can overflow [1] and
\fBWantToUseSafeFunctions\fP is set to \fItrue\fP and it is possible to
obtain the capacity of the destination array then the new function could be
the safe version (ending with \fBcpy_s\fP).
.IP \(bu 2
If the new function is could be safe version and C++ files are analyzed and
the destination array is plain \fBchar\fP/\fBwchar_t\fP without \fBun/signed\fP
then the length of the destination array can be omitted.
.IP \(bu 2
If the new function is could be safe version and the destination array is
\fBun/signed\fP it needs to be casted to plain \fBchar *\fP/\fBwchar_t *\fP\&.
.UNINDENT
.INDENT 0.0
.TP
.B [1] It is possible to overflow:
.INDENT 7.0
.IP \(bu 2
If the capacity of the destination array is unknown.
.IP \(bu 2
If the given length is equal to the destination array\(aqs capacity.
.UNINDENT
.UNINDENT
.SS Rewrite based on the length of the source string
.INDENT 0.0
.IP \(bu 2
If the given length is \fBstrlen(source)\fP or equal length of this expression
then the new function should be the older copy function (ending with
\fBcpy\fP), as it is more efficient than the safe version (ending with
\fBcpy_s\fP).
.IP \(bu 2
Otherwise we assume that the programmer wanted to copy \(aqN\(aq characters, so the
new function is \fBncpy\fP\-like which copies \(aqN\(aq characters.
.UNINDENT
.SS Transformations with \(aqstrlen()\(aq or equal length of this expression
.sp
It transforms the \fBwchar_t\fP based memory and string handler functions
respectively (where only \fBstrerror_s\fP does not have \fBwchar_t\fP based alias).
.SS Memory handler functions
.sp
\fBmemcpy\fP
Please visit the
Transformation rules of \(aqmemcpy()\(aq section.
.sp
\fBmemchr\fP
Usually there is a C\-style cast and it is needed to be removed, because the
new function \fBstrchr\fP\(aqs return type is correct. The given length is going
to be removed.
.sp
\fBmemmove\fP
If safe functions are available the new function is \fBmemmove_s\fP, which has
a new second argument which is the length of the destination array, it is
adjusted, and the length of the source string is incremented by one.
If safe functions are not available the given length is incremented by one.
.sp
\fBmemmove_s\fP
The given length is incremented by one.
.SS String handler functions
.sp
\fBstrerror_s\fP
The given length is incremented by one.
.sp
\fBstrncmp\fP
If the third argument is the first or the second argument\(aqs \fBlength + 1\fP
it has to be truncated without the \fB+ 1\fP operation.
.sp
\fBstrxfrm\fP
The given length is incremented by one.
.SS Options
.INDENT 0.0
.TP
.B WantToUseSafeFunctions
The value \fItrue\fP specifies that the target environment is considered to
implement \(aq_s\(aq suffixed memory and string handler functions which are safer
than older versions (e.g. \(aqmemcpy_s()\(aq). The default value is \fItrue\fP\&.
.UNINDENT
.SS bugprone\-optional\-value\-conversion
.sp
Detects potentially unintentional and redundant conversions where a value is
extracted from an optional\-like type and then used to create a new instance of
the same optional\-like type.
.sp
These conversions might be the result of developer oversight, leftovers from
code refactoring, or other situations that could lead to unintended exceptions
or cases where the resulting optional is always initialized, which might be
unexpected behavior.
.sp
To illustrate, consider the following problematic code snippet:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
#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());
// ...
}
.EE
.UNINDENT
.UNINDENT
.sp
A better approach would be to directly pass \fBopt\fP to the \fBprint\fP function
without extracting its value:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
#include
void print(std::optional);
int main()
{
std::optional opt;
// ...
// Proposed code: Directly pass the std::optional to the print
// function.
print(opt);
// ...
}
.EE
.UNINDENT
.UNINDENT
.sp
By passing \fBopt\fP directly to the print function, unnecessary conversions are
avoided, and potential unintended behavior or exceptions are minimized.
.sp
Value extraction using \fBoperator *\fP is matched by default.
The support for non\-standard optional types such as \fBboost::optional\fP or
\fBabsl::optional\fP may be limited.
.SS Options:
.INDENT 0.0
.TP
.B OptionalTypes
Semicolon\-separated list of (fully qualified) optional type names or regular
expressions that match the optional types.
Default value is \fI::std::optional;::absl::optional;::boost::optional\fP\&.
.UNINDENT
.INDENT 0.0
.TP
.B ValueMethods
Semicolon\-separated list of (fully qualified) method names or regular
expressions that match the methods.
Default value is \fI::value$;::get$\fP\&.
.UNINDENT
.SS bugprone\-parent\-virtual\-call
.sp
Detects and fixes calls to grand\-...parent virtual methods instead of calls
to overridden parent\(aqs virtual methods.
.INDENT 0.0
.INDENT 3.5
.sp
.EX
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 \(aqB\(aq? [bugprone\-parent\-virtual\-call]
};
.EE
.UNINDENT
.UNINDENT
.SS bugprone\-pointer\-arithmetic\-on\-polymorphic\-object
.sp
Finds pointer arithmetic performed on classes that contain a virtual function.
.sp
Pointer arithmetic on polymorphic objects where the pointer\(aqs static type is
different from its dynamic type is undefined behavior, as the two types could
have different sizes, and thus the vtable pointer could point to an
invalid address.
.sp
Finding pointers where the static type contains a virtual member function is a
good heuristic, as the pointer is likely to point to a different,
derived object.
.sp
Example:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
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
}
.EE
.UNINDENT
.UNINDENT
.SS Options
.INDENT 0.0
.TP
.B IgnoreInheritedVirtualFunctions
When \fItrue\fP, objects that only inherit a virtual function are not checked.
Classes that do not declare a new virtual function are excluded
by default, as they make up the majority of false positives.
Default: \fIfalse\fP\&.
.INDENT 7.0
.INDENT 3.5
.sp
.EX
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
}
.EE
.UNINDENT
.UNINDENT
.UNINDENT
.SS References
.sp
This check corresponds to the SEI Cert rule
CTR56\-CPP. Do not use pointer arithmetic on polymorphic objects \%\&.
.SS bugprone\-posix\-return
.sp
Checks if any calls to \fBpthread_*\fP or \fBposix_*\fP functions
(except \fBposix_openpt\fP) expect negative return values. These functions return
either \fB0\fP on success or an \fBerrno\fP on failure, which is positive only.
.sp
Example buggy usage looks like:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
if (posix_fadvise(...) < 0) {
.EE
.UNINDENT
.UNINDENT
.sp
This will never happen as the return value is always non\-negative.
A simple fix could be:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
if (posix_fadvise(...) > 0) {
.EE
.UNINDENT
.UNINDENT
.SS bugprone\-random\-generator\-seed
.sp
Flags all pseudo\-random number engines, engine adaptor
instantiations and \fBsrand()\fP when initialized or seeded with default
argument, constant expression or any user\-configurable type. Pseudo\-random
number engines seeded with a predictable value may cause vulnerabilities
e.g. in security protocols.
.sp
Examples:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
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
}
.EE
.UNINDENT
.UNINDENT
.SS Options
.INDENT 0.0
.TP
.B DisallowedSeedTypes
A comma\-separated list of the type names which are disallowed.
Default value is \fItime_t,std::time_t\fP\&.
.UNINDENT
.SS References
.sp
This check corresponds to the CERT C++ Coding Standard rules
MSC51\-CPP. Ensure your random number generator is properly seeded \% and
MSC32\-C. Properly seed pseudorandom number generators \%\&.
.SS bugprone\-raw\-memory\-call\-on\-non\-trivial\-type
.sp
Flags use of the C standard library functions \fBmemset\fP, \fBmemcpy\fP and
\fBmemcmp\fP and similar derivatives on non\-trivial types.
.sp
The check will detect the following functions: \fBmemset\fP, \fBstd::memset\fP,
\fBstd::memcpy\fP, \fBmemcpy\fP, \fBstd::memmove\fP, \fBmemmove\fP, \fBstd::strcpy\fP,
\fBstrcpy\fP, \fBmemccpy\fP, \fBstpncpy\fP, \fBstrncpy\fP, \fBstd::memcmp\fP, \fBmemcmp\fP,
\fBstd::strcmp\fP, \fBstrcmp\fP, \fBstrncmp\fP\&.
.SS Options
.INDENT 0.0
.TP
.B MemSetNames
Specify extra functions to flag that act similarly to \fBmemset\fP\&. Specify
names in a semicolon\-delimited list. Default is an empty string.
.UNINDENT
.INDENT 0.0
.TP
.B MemCpyNames
Specify extra functions to flag that act similarly to \fBmemcpy\fP\&. Specify
names in a semicolon\-delimited list. Default is an empty string.
.UNINDENT
.INDENT 0.0
.TP
.B MemCmpNames
Specify extra functions to flag that act similarly to \fBmemcmp\fP\&. Specify
names in a semicolon\-delimited list. Default is an empty string.
.UNINDENT
.sp
This check corresponds to the CERT C++ Coding Standard rule
OOP57\-CPP. Prefer special member functions and overloaded operators to C
Standard Library functions \%\&.
.SS bugprone\-redundant\-branch\-condition
.sp
Finds condition variables in nested \fBif\fP statements that were also checked in
the outer \fBif\fP statement and were not changed.
.sp
Simple example:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
bool onFire = isBurning();
if (onFire) {
if (onFire)
scream();
}
.EE
.UNINDENT
.UNINDENT
.sp
Here \fIonFire\fP is checked both in the outer \fBif\fP and the inner \fBif\fP
statement without a possible change between the two checks. The check warns for
this code and suggests removal of the second checking of variable \fIonFire\fP\&.
.sp
The checker also detects redundant condition checks if the condition variable
is an operand of a logical \(dqand\(dq (\fB&&\fP) or a logical \(dqor\(dq (\fB||\fP) operator:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
bool onFire = isBurning();
if (onFire) {
if (onFire && peopleInTheBuilding > 0)
scream();
}
.EE
.UNINDENT
.UNINDENT
.INDENT 0.0
.INDENT 3.5
.sp
.EX
bool onFire = isBurning();
if (onFire) {
if (onFire || isCollapsing())
scream();
}
.EE
.UNINDENT
.UNINDENT
.sp
In the first case (logical \(dqand\(dq) the suggested fix is to remove the redundant
condition variable and keep the other side of the \fB&&\fP\&. In the second case
(logical \(dqor\(dq) the whole \fBif\fP is removed similarly to the simple case on the
top.
.sp
The condition of the outer \fBif\fP statement may also be a logical \(dqand\(dq
(\fB&&\fP) expression:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
bool onFire = isBurning();
if (onFire && fireFighters < 10) {
if (someOtherCondition()) {
if (onFire)
scream();
}
}
.EE
.UNINDENT
.UNINDENT
.sp
The error is also detected if both the outer statement is a logical \(dqand\(dq
(\fB&&\fP) and the inner statement is a logical \(dqand\(dq (\fB&&\fP) or \(dqor\(dq (\fB||\fP).
The inner \fBif\fP statement does not have to be a direct descendant of the outer
one.
.sp
No error is detected if the condition variable may have been changed between
the two checks:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
bool onFire = isBurning();
if (onFire) {
tryToExtinguish(onFire);
if (onFire && peopleInTheBuilding > 0)
scream();
}
.EE
.UNINDENT
.UNINDENT
.sp
Every possible change is considered, thus if the condition variable is not
a local variable of the function, it is a volatile or it has an alias (pointer
or reference) then no warning is issued.
.SS Limitations
.sp
The \fBelse\fP branch is not checked currently for negated condition variable:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
bool onFire = isBurning();
if (onFire) {
scream();
} else {
if (!onFire) {
continueWork();
}
}
.EE
.UNINDENT
.UNINDENT
.sp
The checker currently only detects redundant checking of single condition
variables. More complex expressions are not checked:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
if (peopleInTheBuilding == 1) {
if (peopleInTheBuilding == 1) {
doSomething();
}
}
.EE
.UNINDENT
.UNINDENT
.SS bugprone\-reserved\-identifier
.sp
\fIcert\-dcl37\-c\fP and \fIcert\-dcl51\-cpp\fP redirect here as an alias for this check.
.sp
Checks for usages of identifiers reserved for use by the implementation.
.sp
The C and C++ standards both reserve the following names for such use:
.INDENT 0.0
.IP \(bu 2
identifiers that begin with an underscore followed by an uppercase letter;
.IP \(bu 2
identifiers in the global namespace that begin with an underscore.
.UNINDENT
.sp
The C standard additionally reserves names beginning with a double underscore,
while the C++ standard strengthens this to reserve names with a double
underscore occurring anywhere.
.sp
Violating the naming rules above results in undefined behavior.
.INDENT 0.0
.INDENT 3.5
.sp
.EX
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
.EE
.UNINDENT
.UNINDENT
.sp
The check can also be inverted, i.e. it can be configured to flag any
identifier that is \fInot\fP a reserved identifier. This mode is for use by e.g.
standard library implementors, to ensure they don\(aqt infringe on the user
namespace.
.sp
This check does not (yet) check for other reserved names, e.g. macro names
identical to language keywords, and names specifically reserved by language
standards, e.g. C++ \(aqzombie names\(aq and C future library directions.
.sp
This check corresponds to CERT C Coding Standard rule DCL37\-C. Do not declare
or define a reserved identifier \%
as well as its C++ counterpart, DCL51\-CPP. Do not declare or define a reserved
identifier \%\&.
.SS Options
.INDENT 0.0
.TP
.B Invert
If \fItrue\fP, inverts the check, i.e. flags names that are not reserved.
Default is \fIfalse\fP\&.
.UNINDENT
.INDENT 0.0
.TP
.B AllowedIdentifiers
Semicolon\-separated list of regular expressions that the check ignores. Default is an
empty list.
.UNINDENT
.SS bugprone\-return\-const\-ref\-from\-parameter
.sp
Detects return statements that return a constant reference parameter as
constant reference. This may cause use\-after\-free errors if the caller
uses xvalues as arguments.
.sp
In C++, constant reference parameters can accept xvalues which will be
destructed after the call. When the function returns such a parameter also
as constant reference, then the returned reference can be used after the
object it refers to has been destroyed.
.SS Example
.INDENT 0.0
.INDENT 3.5
.sp
.EX
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
.EE
.UNINDENT
.UNINDENT
.sp
This issue can be resolved by declaring an overload of the problematic function
where the \fBconst &\fP parameter is instead declared as \fB&&\fP\&. The developer has
to ensure that the implementation of that function does not produce a
use\-after\-free, the exact error that this check is warning against.
Marking such an \fB&&\fP overload as \fBdeleted\fP, will silence the warning as
well. In the case of different \fBconst &\fP parameters being returned depending
on the control flow of the function, an overload where all problematic
\fBconst &\fP parameters have been declared as \fB&&\fP will resolve the issue.
.sp
This issue can also be resolved by adding \fB[[clang::lifetimebound]]\fP\&. Clang
enable \fB\-Wdangling\fP warning by default which can detect mis\-uses of the
annotated function. See lifetimebound attribute \%
for details.
.INDENT 0.0
.INDENT 3.5
.sp
.EX
const int &f(const int &a [[clang::lifetimebound]]) { return a; } // no warning
const int &v = f(1); // warning: temporary bound to local reference \(aqv\(aq will be destroyed at the end of the full\-expression [\-Wdangling]
.EE
.UNINDENT
.UNINDENT
.SS bugprone\-shared\-ptr\-array\-mismatch
.sp
Finds initializations of C++ shared pointers to non\-array type that are
initialized with an array.
.sp
If a shared pointer \fBstd::shared_ptr\fP is initialized with a new\-expression
\fBnew T[]\fP the memory is not deallocated correctly. The pointer uses plain
\fBdelete\fP in this case to deallocate the target memory. Instead a \fBdelete[]\fP
call is needed. A \fBstd::shared_ptr\fP calls the correct delete operator.
.sp
The check offers replacement of \fBshared_ptr\fP to \fBshared_ptr\fP if it
is used at a single variable declaration (one variable in one statement).
.sp
Example:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
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]
};
.EE
.UNINDENT
.UNINDENT
.sp
This check partially covers the CERT C++ Coding Standard rule
MEM51\-CPP. Properly deallocate dynamically allocated resources \%
However, only the \fBstd::shared_ptr\fP case is detected by this check.
.SS bugprone\-signal\-handler
.sp
Finds specific constructs in signal handler functions that can cause undefined
behavior. The rules for what is allowed differ between C++ language versions.
.sp
Checked signal handler rules for C:
.INDENT 0.0
.IP \(bu 2
Calls to non\-asynchronous\-safe functions are not allowed.
.UNINDENT
.sp
Checked signal handler rules for up to and including C++14:
.INDENT 0.0
.IP \(bu 2
Calls to non\-asynchronous\-safe functions are not allowed.
.IP \(bu 2
C++\-specific code constructs are not allowed in signal handlers.
In other words, only the common subset of C and C++ is allowed to be used.
.IP \(bu 2
Calls to functions with non\-C linkage are not allowed (including the signal
handler itself).
.UNINDENT
.sp
The check is disabled on C++17 and later.
.sp
Asynchronous\-safety is determined by comparing the function\(aqs name against a
set of known functions. In addition, the function must come from a system
header include and in a global namespace. The (possible) arguments passed to
the function are not checked. Any function that cannot be determined to be
asynchronous\-safe is assumed to be non\-asynchronous\-safe by the check,
including user functions for which only the declaration is visible.
Calls to user\-defined functions with visible definitions are checked
recursively.
.sp
This check implements the CERT C Coding Standard rule
SIG30\-C. Call only asynchronous\-safe functions within signal handlers \%
and the rule
MSC54\-CPP. A signal handler must be a plain old function \%\&.
It has the alias names \fBcert\-sig30\-c\fP and \fBcert\-msc54\-cpp\fP\&.
.SS Options
.INDENT 0.0
.TP
.B AsyncSafeFunctionSet
Selects which set of functions is considered as asynchronous\-safe
(and therefore allowed in signal handlers). It can be set to the following values:
.INDENT 7.0
.IP \(bu 2
.INDENT 2.0
.TP
.B \fIminimal\fP
Selects a minimal set that is defined in the CERT SIG30\-C rule.
and includes functions \fBabort()\fP, \fB_Exit()\fP, \fBquick_exit()\fP and
\fBsignal()\fP\&.
.UNINDENT
.IP \(bu 2
.INDENT 2.0
.TP
.B \fIPOSIX\fP
Selects a larger set of functions that is listed in POSIX.1\-2017 (see this
link \%
for more information). The following functions are included:
\fB_Exit\fP, \fB_exit\fP, \fBabort\fP, \fBaccept\fP, \fBaccess\fP, \fBaio_error\fP,
\fBaio_return\fP, \fBaio_suspend\fP, \fBalarm\fP, \fBbind\fP, \fBcfgetispeed\fP,
\fBcfgetospeed\fP, \fBcfsetispeed\fP, \fBcfsetospeed\fP, \fBchdir\fP, \fBchmod\fP,
\fBchown\fP, \fBclock_gettime\fP, \fBclose\fP, \fBconnect\fP, \fBcreat\fP, \fBdup\fP,
\fBdup2\fP, \fBexecl\fP, \fBexecle\fP, \fBexecv\fP, \fBexecve\fP, \fBfaccessat\fP,
\fBfchdir\fP, \fBfchmod\fP, \fBfchmodat\fP, \fBfchown\fP, \fBfchownat\fP, \fBfcntl\fP,
\fBfdatasync\fP, \fBfexecve\fP, \fBffs\fP, \fBfork\fP, \fBfstat\fP, \fBfstatat\fP,
\fBfsync\fP, \fBftruncate\fP, \fBfutimens\fP, \fBgetegid\fP, \fBgeteuid\fP,
\fBgetgid\fP, \fBgetgroups\fP, \fBgetpeername\fP, \fBgetpgrp\fP, \fBgetpid\fP,
\fBgetppid\fP, \fBgetsockname\fP, \fBgetsockopt\fP, \fBgetuid\fP, \fBhtonl\fP,
\fBhtons\fP, \fBkill\fP, \fBlink\fP, \fBlinkat\fP, \fBlisten\fP, \fBlongjmp\fP,
\fBlseek\fP, \fBlstat\fP, \fBmemccpy\fP, \fBmemchr\fP, \fBmemcmp\fP, \fBmemcpy\fP,
\fBmemmove\fP, \fBmemset\fP, \fBmkdir\fP, \fBmkdirat\fP, \fBmkfifo\fP, \fBmkfifoat\fP,
\fBmknod\fP, \fBmknodat\fP, \fBntohl\fP, \fBntohs\fP, \fBopen\fP, \fBopenat\fP,
\fBpause\fP, \fBpipe\fP, \fBpoll\fP, \fBposix_trace_event\fP, \fBpselect\fP,
\fBpthread_kill\fP, \fBpthread_self\fP, \fBpthread_sigmask\fP, \fBquick_exit\fP,
\fBraise\fP, \fBread\fP, \fBreadlink\fP, \fBreadlinkat\fP, \fBrecv\fP, \fBrecvfrom\fP,
\fBrecvmsg\fP, \fBrename\fP, \fBrenameat\fP, \fBrmdir\fP, \fBselect\fP, \fBsem_post\fP,
\fBsend\fP, \fBsendmsg\fP, \fBsendto\fP, \fBsetgid\fP, \fBsetpgid\fP, \fBsetsid\fP,
\fBsetsockopt\fP, \fBsetuid\fP, \fBshutdown\fP, \fBsigaction\fP, \fBsigaddset\fP,
\fBsigdelset\fP, \fBsigemptyset\fP, \fBsigfillset\fP, \fBsigismember\fP,
\fBsiglongjmp\fP, \fBsignal\fP, \fBsigpause\fP, \fBsigpending\fP, \fBsigprocmask\fP,
\fBsigqueue\fP, \fBsigset\fP, \fBsigsuspend\fP, \fBsleep\fP, \fBsockatmark\fP,
\fBsocket\fP, \fBsocketpair\fP, \fBstat\fP, \fBstpcpy\fP, \fBstpncpy\fP,
\fBstrcat\fP, \fBstrchr\fP, \fBstrcmp\fP, \fBstrcpy\fP, \fBstrcspn\fP, \fBstrlen\fP,
\fBstrncat\fP, \fBstrncmp\fP, \fBstrncpy\fP, \fBstrnlen\fP, \fBstrpbrk\fP,
\fBstrrchr\fP, \fBstrspn\fP, \fBstrstr\fP, \fBstrtok_r\fP, \fBsymlink\fP,
\fBsymlinkat\fP, \fBtcdrain\fP, \fBtcflow\fP, \fBtcflush\fP, \fBtcgetattr\fP,
\fBtcgetpgrp\fP, \fBtcsendbreak\fP, \fBtcsetattr\fP, \fBtcsetpgrp\fP,
\fBtime\fP, \fBtimer_getoverrun\fP, \fBtimer_gettime\fP, \fBtimer_settime\fP,
\fBtimes\fP, \fBumask\fP, \fBuname\fP, \fBunlink\fP, \fBunlinkat\fP, \fButime\fP,
\fButimensat\fP, \fButimes\fP, \fBwait\fP, \fBwaitpid\fP, \fBwcpcpy\fP,
\fBwcpncpy\fP, \fBwcscat\fP, \fBwcschr\fP, \fBwcscmp\fP, \fBwcscpy\fP, \fBwcscspn\fP,
\fBwcslen\fP, \fBwcsncat\fP, \fBwcsncmp\fP, \fBwcsncpy\fP, \fBwcsnlen\fP, \fBwcspbrk\fP,
\fBwcsrchr\fP, \fBwcsspn\fP, \fBwcsstr\fP, \fBwcstok\fP, \fBwmemchr\fP, \fBwmemcmp\fP,
\fBwmemcpy\fP, \fBwmemmove\fP, \fBwmemset\fP, \fBwrite\fP
.sp
The function \fBquick_exit\fP is not included in the POSIX list but it
is included here in the set of safe functions.
.UNINDENT
.UNINDENT
.sp
The default value is \fIPOSIX\fP\&.
.UNINDENT
.SS bugprone\-signed\-char\-misuse
.sp
\fIcert\-str34\-c\fP redirects here as an alias for this check. For the CERT alias,
the \fIDiagnoseSignedUnsignedCharComparisons\fP option is set to \fIfalse\fP\&.
.sp
Finds those \fBsigned char\fP \-> integer conversions which might indicate a
programming error. The basic problem with the \fBsigned char\fP, that it might
store the non\-ASCII characters as negative values. This behavior can cause a
misunderstanding of the written code both when an explicit and when an
implicit conversion happens.
.sp
When the code contains an explicit \fBsigned char\fP \-> integer conversion, the
human programmer probably expects that the converted value matches with the
character code (a value from [0..255]), however, the actual value is in
[\-128..127] interval. To avoid this kind of misinterpretation, the desired way
of converting from a \fBsigned char\fP to an integer value is converting to
\fBunsigned char\fP first, which stores all the characters in the positive
[0..255] interval which matches the known character codes.
.sp
In case of implicit conversion, the programmer might not actually be aware
that a conversion happened and char value is used as an integer. There are
some use cases when this unawareness might lead to a functionally imperfect
code. For example, checking the equality of a \fBsigned char\fP and an
\fBunsigned char\fP variable is something we should avoid in C++ code. During
this comparison, the two variables are converted to integers which have
different value ranges. For \fBsigned char\fP, the non\-ASCII characters are
stored as a value in [\-128..\-1] interval, while the same characters are
stored in the [128..255] interval for an \fBunsigned char\fP\&.
.sp
It depends on the actual platform whether plain \fBchar\fP is handled as
\fBsigned char\fP by default and so it is caught by this check or not.
To change the default behavior you can use \fB\-funsigned\-char\fP and
\fB\-fsigned\-char\fP compilation options.
.sp
Currently, this check warns in the following cases:
.INDENT 0.0
.IP \(bu 2
\fBsigned char\fP is assigned to an integer variable
.IP \(bu 2
\fBsigned char\fP and \fBunsigned char\fP are compared with
equality/inequality operator
.IP \(bu 2
\fBsigned char\fP is converted to an integer in the array subscript
.UNINDENT
.sp
See also:
STR34\-C. Cast characters to unsigned char before converting to larger
integer sizes \%
.sp
A good example from the CERT description when a \fBchar\fP variable is used to
read from a file that might contain non\-ASCII characters. The problem comes
up when the code uses the \fB\-1\fP integer value as EOF, while the 255 character
code is also stored as \fB\-1\fP in two\(aqs complement form of char type.
See a simple example of this below. This code stops not only when it reaches
the end of the file, but also when it gets a character with the 255 code.
.INDENT 0.0
.INDENT 3.5
.sp
.EX
#define EOF (\-1)
int read(void) {
char CChar;
int IChar = EOF;
if (readChar(CChar)) {
IChar = CChar;
}
return IChar;
}
.EE
.UNINDENT
.UNINDENT
.sp
A proper way to fix the code above is converting the \fBchar\fP variable to
an \fBunsigned char\fP value first.
.INDENT 0.0
.INDENT 3.5
.sp
.EX
#define EOF (\-1)
int read(void) {
char CChar;
int IChar = EOF;
if (readChar(CChar)) {
IChar = static_cast(CChar);
}
return IChar;
}
.EE
.UNINDENT
.UNINDENT
.sp
Another use case is checking the equality of two \fBchar\fP variables with
different signedness. Inside the non\-ASCII value range this comparison between
a \fBsigned char\fP and an \fBunsigned char\fP always returns \fBfalse\fP\&.
.INDENT 0.0
.INDENT 3.5
.sp
.EX
bool compare(signed char SChar, unsigned char USChar) {
if (SChar == USChar)
return true;
return false;
}
.EE
.UNINDENT
.UNINDENT
.sp
The easiest way to fix this kind of comparison is casting one of the arguments,
so both arguments will have the same type.
.INDENT 0.0
.INDENT 3.5
.sp
.EX
bool compare(signed char SChar, unsigned char USChar) {
if (static_cast(SChar) == USChar)
return true;
return false;
}
.EE
.UNINDENT
.UNINDENT
.SS Options
.INDENT 0.0
.TP
.B CharTypedefsToIgnore
A semicolon\-separated list of typedef names. In this list, we can list
typedefs for \fBchar\fP or \fBsigned char\fP, which will be ignored by the
check. This is useful when a typedef introduces an integer alias like
\fBsal_Int8\fP or \fBint8_t\fP\&. In this case, human misinterpretation is not
an issue. Default is an empty string.
.UNINDENT
.INDENT 0.0
.TP
.B DiagnoseSignedUnsignedCharComparisons
When \fItrue\fP, the check will warn on \fBsigned char\fP/\fBunsigned char\fP comparisons,
otherwise these comparisons are ignored. By default, this option is set to \fItrue\fP\&.
.UNINDENT
.SS bugprone\-sizeof\-container
.sp
The check finds usages of \fBsizeof\fP on expressions of STL container types.
Most likely the user wanted to use \fB\&.size()\fP instead.
.sp
All class/struct types declared in namespace \fBstd::\fP having a const
\fBsize()\fP method are considered containers, with the exception of
\fBstd::bitset\fP and \fBstd::array\fP\&.
.sp
Examples:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
std::string s;
int a = 47 + sizeof(s); // warning: sizeof() doesn\(aqt 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.
.EE
.UNINDENT
.UNINDENT
.SS bugprone\-sizeof\-expression
.sp
The check finds usages of \fBsizeof\fP expressions which are most likely errors.
.sp
The \fBsizeof\fP operator yields the size (in bytes) of its operand, which may be
an expression or the parenthesized name of a type. Misuse of this operator may
be leading to errors and possible software vulnerabilities.
.SS Suspicious usage of \(aqsizeof(K)\(aq
.sp
A common mistake is to query the \fBsizeof\fP of an integer literal. This is
equivalent to query the size of its type (probably \fBint\fP). The intent of the
programmer was probably to simply get the integer and not its size.
.INDENT 0.0
.INDENT 3.5
.sp
.EX
#define BUFLEN 42
char buf[BUFLEN];
memset(buf, 0, sizeof(BUFLEN)); // sizeof(42) ==> sizeof(int)
.EE
.UNINDENT
.UNINDENT
.SS Suspicious usage of \(aqsizeof(expr)\(aq
.sp
In cases, where there is an enum or integer to represent a type, a common
mistake is to query the \fBsizeof\fP on the integer or enum that represents the
type that should be used by \fBsizeof\fP\&. This results in the size of the integer
and not of the type the integer represents:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
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());
...
}
.EE
.UNINDENT
.UNINDENT
.SS Suspicious usage of \(aqsizeof(this)\(aq
.sp
The \fBthis\fP keyword is evaluated to a pointer to an object of a given type.
The expression \fBsizeof(this)\fP is returning the size of a pointer. The
programmer most likely wanted the size of the object and not the size of the
pointer.
.INDENT 0.0
.INDENT 3.5
.sp
.EX
class Point {
[...]
size_t size() { return sizeof(this); } // should probably be sizeof(*this)
[...]
};
.EE
.UNINDENT
.UNINDENT
.SS Suspicious usage of \(aqsizeof(char*)\(aq
.sp
There is a subtle difference between declaring a string literal with
\fBchar* A = \(dq\(dq\fP and \fBchar A[] = \(dq\(dq\fP\&. The first case has the type \fBchar*\fP
instead of the aggregate type \fBchar[]\fP\&. Using \fBsizeof\fP on an object
declared with \fBchar*\fP type is returning the size of a pointer instead of
the number of characters (bytes) in the string literal.
.INDENT 0.0
.INDENT 3.5
.sp
.EX
const char* kMessage = \(dqHello World!\(dq; // const char kMessage[] = \(dq...\(dq;
void getMessage(char* buf) {
memcpy(buf, kMessage, sizeof(kMessage)); // sizeof(char*)
}
.EE
.UNINDENT
.UNINDENT
.SS Suspicious usage of \(aqsizeof(A*)\(aq
.sp
A common mistake is to compute the size of a pointer instead of its pointee.
These cases may occur because of explicit cast or implicit conversion.
.INDENT 0.0
.INDENT 3.5
.sp
.EX
int A[10];
memset(A, 0, sizeof(A + 0));
struct Point point;
memset(point, 0, sizeof(&point));
.EE
.UNINDENT
.UNINDENT
.SS Suspicious usage of \(aqsizeof(...)/sizeof(...)\(aq
.sp
Dividing \fBsizeof\fP expressions is typically used to retrieve the number of
elements of an aggregate. This check warns on incompatible or suspicious cases.
.sp
In the following example, the entity has 10\-bytes and is incompatible with the
type \fBint\fP which has 4 bytes.
.INDENT 0.0
.INDENT 3.5
.sp
.EX
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]
}
.EE
.UNINDENT
.UNINDENT
.sp
In the following example, the expression \fBsizeof(Values)\fP is returning the
size of \fBchar*\fP\&. One can easily be fooled by its declaration, but in parameter
declaration the size \(aq10\(aq is ignored and the function is receiving a \fBchar*\fP\&.
.INDENT 0.0
.INDENT 3.5
.sp
.EX
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*]
}
.EE
.UNINDENT
.UNINDENT
.SS Suspicious \(aqsizeof\(aq by \(aqsizeof\(aq expression
.sp
Multiplying \fBsizeof\fP expressions typically makes no sense and is probably a
logic error. In the following example, the programmer used \fB*\fP instead of
\fB/\fP\&.
.INDENT 0.0
.INDENT 3.5
.sp
.EX
const char kMessage[] = \(dqHello World!\(dq;
void getMessage(char* buf) {
memcpy(buf, kMessage, sizeof(kMessage) * sizeof(char)); // sizeof(kMessage) / sizeof(char)
}
.EE
.UNINDENT
.UNINDENT
.sp
This check may trigger on code using the arraysize macro. The following code is
working correctly but should be simplified by using only the \fBsizeof\fP
operator.
.INDENT 0.0
.INDENT 3.5
.sp
.EX
extern Object objects[100];
void InitializeObjects() {
memset(objects, 0, arraysize(objects) * sizeof(Object)); // sizeof(objects)
}
.EE
.UNINDENT
.UNINDENT
.SS Suspicious usage of \(aqsizeof(sizeof(...))\(aq
.sp
Getting the \fBsizeof\fP of a \fBsizeof\fP makes no sense and is typically an error
hidden through macros.
.INDENT 0.0
.INDENT 3.5
.sp
.EX
#define INT_SZ sizeof(int)
int buf[] = { 42 };
void getInt(int* dst) {
memcpy(dst, buf, sizeof(INT_SZ)); // sizeof(sizeof(int)) is suspicious.
}
.EE
.UNINDENT
.UNINDENT
.SS Suspicious usages of \(aqsizeof(...)\(aq in pointer arithmetic
.sp
Arithmetic operators on pointers automatically scale the result with the size
of the pointed typed.
Further use of \fBsizeof\fP around pointer arithmetic will typically result in an
unintended result.
.SS Scaling the result of pointer difference
.sp
Subtracting two pointers results in an integer expression (of type
\fBptrdiff_t\fP) which expresses the distance between the two pointed objects in
\(dqnumber of objects between\(dq.
A common mistake is to think that the result is \(dqnumber of bytes between\(dq, and
scale the difference with \fBsizeof\fP, such as \fBP1 \- P2 == N * sizeof(T)\fP
(instead of \fBP1 \- P2 == N\fP) or \fB(P1 \- P2) / sizeof(T)\fP instead of
\fBP1 \- P2\fP\&.
.INDENT 0.0
.INDENT 3.5
.sp
.EX
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();
}
}
.EE
.UNINDENT
.UNINDENT
.INDENT 0.0
.INDENT 3.5
.sp
.EX
void iterateIfEvenLength(int *Begin, int *End) {
auto N = (Begin \- End) / sizeof(int); // Dividing by sizeof() is suspicious.
if (N % 2)
return;
// ...
}
.EE
.UNINDENT
.UNINDENT
.SS Stepping a pointer with a scaled integer
.sp
Conversely, when performing pointer arithmetics to add or subtract from a
pointer, the arithmetic operator implicitly scales the value actually added to
the pointer with the size of the pointee, as \fBPtr + N\fP expects \fBN\fP to be
\(dqnumber of objects to step\(dq, and not \(dqnumber of bytes to step\(dq.
.sp
Seeing the calculation of a pointer where \fBsizeof\fP appears is suspicious,
and the result is typically unintended, often out of bounds.
\fBPtr + sizeof(T)\fP will offset the pointer by \fBsizeof(T)\fP elements,
effectively exponentiating the scaling factor to the power of 2.
.sp
Similarly, multiplying or dividing a numeric value with the \fBsizeof\fP of an
element or the whole buffer is suspicious, because the dimensional connection
between the numeric value and the actual \fBsizeof\fP result can not always be
deduced.
While scaling an integer up (multiplying) with \fBsizeof\fP is likely \fBalways\fP
an issue, a scaling down (division) is not always inherently dangerous, in case
the developer is aware that the division happens between an appropriate number
of _bytes_ and a \fBsizeof\fP value.
Turning \fBWarnOnOffsetDividedBySizeOf\fP off will restrict the
warnings to the multiplication case.
.sp
This case also checks suspicious \fBalignof\fP and \fBoffsetof\fP usages in
pointer arithmetic, as both return the \(dqsize\(dq in bytes and not elements,
potentially resulting in doubly\-scaled offsets.
.INDENT 0.0
.INDENT 3.5
.sp
.EX
void printEveryEvenIndexElement(int *Array, size_t N) {
int *P = Array;
while (P <= Array + N * sizeof(int)) { // Suspicious pointer arithmetic using sizeof()!
printf(\(dq%d \(dq, *P);
P += 2 * sizeof(int); // Suspicious pointer arithmetic using sizeof()!
}
}
.EE
.UNINDENT
.UNINDENT
.INDENT 0.0
.INDENT 3.5
.sp
.EX
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;
}
}
.EE
.UNINDENT
.UNINDENT
.sp
For this checked bogus pattern, \fIcert\-arr39\-c\fP redirects here as an alias of
this check.
.sp
This check corresponds to the CERT C Coding Standard rule
ARR39\-C. Do not add or subtract a scaled integer to a pointer \%\&.
.SS Limitations
.sp
Cases where the pointee type has a size of \fI1\fP byte (such as, and most
importantly, \fBchar\fP) are excluded.
.SS Options
.INDENT 0.0
.TP
.B WarnOnSizeOfConstant
When \fItrue\fP, the check will warn on an expression like
\fBsizeof(CONSTANT)\fP\&. Default is \fItrue\fP\&.
.UNINDENT
.INDENT 0.0
.TP
.B WarnOnSizeOfIntegerExpression
When \fItrue\fP, the check will warn on an expression like \fBsizeof(expr)\fP
where the expression results in an integer. Default is \fIfalse\fP\&.
.UNINDENT
.INDENT 0.0
.TP
.B WarnOnSizeOfThis
When \fItrue\fP, the check will warn on an expression like \fBsizeof(this)\fP\&.
Default is \fItrue\fP\&.
.UNINDENT
.INDENT 0.0
.TP
.B WarnOnSizeOfCompareToConstant
When \fItrue\fP, the check will warn on an expression like
\fBsizeof(expr) <= k\fP for a suspicious constant \fIk\fP while \fIk\fP is \fI0\fP or
greater than \fI0x8000\fP\&. Default is \fItrue\fP\&.
.UNINDENT
.INDENT 0.0
.TP
.B WarnOnSizeOfPointerToAggregate
When \fItrue\fP, the check will warn when the argument of \fBsizeof\fP is either a
pointer\-to\-aggregate type, an expression returning a pointer\-to\-aggregate
value or an expression that returns a pointer from an array\-to\-pointer
conversion (that may be implicit or explicit, for example \fBarray + 2\fP or
\fB(int *)array\fP). Default is \fItrue\fP\&.
.UNINDENT
.INDENT 0.0
.TP
.B WarnOnSizeOfPointer
When \fItrue\fP, the check will report all expressions where the argument of
\fBsizeof\fP is an expression that produces a pointer (except for a few
idiomatic expressions that are probably intentional and correct).
This detects occurrences of CWE 467. Default is \fIfalse\fP\&.
.UNINDENT
.INDENT 0.0
.TP
.B WarnOnOffsetDividedBySizeOf
When \fItrue\fP, the check will warn on pointer arithmetic where the
element count is obtained from a division with \fBsizeof(...)\fP,
e.g., \fBPtr + Bytes / sizeof(*T)\fP\&. Default is \fItrue\fP\&.
.UNINDENT
.INDENT 0.0
.TP
.B WarnOnSizeOfInLoopTermination
When \fItrue\fP, the check will warn about incorrect use of sizeof expression
in loop termination condition. The warning triggers if the \fBsizeof\fP
expression appears to be incorrectly used to determine the number of
array/buffer elements.
e.g, \fBlong arr[10]; for(int i = 0; i < sizeof(arr); i++) { ... }\fP\&. Default
is \fItrue\fP\&.
.UNINDENT
.SS bugprone\-spuriously\-wake\-up\-functions
.sp
Finds \fBcnd_wait\fP, \fBcnd_timedwait\fP, \fBwait\fP, \fBwait_for\fP, or
\fBwait_until\fP function calls when the function is not invoked from a loop
that checks whether a condition predicate holds or the function has a
condition parameter.
.INDENT 0.0
.INDENT 3.5
.sp
.EX
if (condition_predicate) {
condition.wait(lk);
}
.EE
.UNINDENT
.UNINDENT
.INDENT 0.0
.INDENT 3.5
.sp
.EX
if (condition_predicate) {
if (thrd_success != cnd_wait(&condition, &lock)) {
}
}
.EE
.UNINDENT
.UNINDENT
.sp
This check corresponds to the CERT C++ Coding Standard rule
CON54\-CPP. Wrap functions that can spuriously wake up in a loop \%\&.
and CERT C Coding Standard rule
CON36\-C. Wrap functions that can spuriously wake up in a loop \%\&.
.SS bugprone\-standalone\-empty
.sp
Warns when \fBempty()\fP is used on a range and the result is ignored. Suggests
\fBclear()\fP if it is an existing member function.
.sp
The \fBempty()\fP method on several common ranges returns a Boolean indicating
whether or not the range is empty, but is often mistakenly interpreted as
a way to clear the contents of a range. Some ranges offer a \fBclear()\fP
method for this purpose. This check warns when a call to empty returns a
result that is ignored, and suggests replacing it with a call to \fBclear()\fP
if it is available as a member function of the range.
.sp
For example, the following code could be used to indicate whether a range
is empty or not, but the result is ignored:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
std::vector v;
\&...
v.empty();
.EE
.UNINDENT
.UNINDENT
.sp
A call to \fBclear()\fP would appropriately clear the contents of the range:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
std::vector v;
\&...
v.clear();
.EE
.UNINDENT
.UNINDENT
.SS Limitations
.INDENT 0.0
.IP \(bu 2
Doesn\(aqt warn if \fBempty()\fP is defined and used with the ignore result in the
class template definition (for example in the library implementation). These
error cases can be caught with \fB[[nodiscard]]\fP attribute.
.UNINDENT
.SS bugprone\-std\-namespace\-modification
.sp
Warns on modifications of the \fBstd\fP or \fBposix\fP namespaces which can
result in undefined behavior.
.sp
The \fBstd\fP (or \fBposix\fP) namespace is allowed to be extended with (class or
function) template specializations that depend on an user\-defined type (a type
that is not defined in the standard system headers).
.sp
The check detects the following (user provided) declarations in namespace
\fBstd\fP or \fBposix\fP:
.INDENT 0.0
.IP \(bu 2
Anything that is not a template specialization.
.IP \(bu 2
Explicit specializations of any standard library function template or class
template, if it does not have any user\-defined type as template argument.
.IP \(bu 2
Explicit specializations of any member function of a standard library class
template.
.IP \(bu 2
Explicit specializations of any member function template of a standard
library class or class template.
.IP \(bu 2
Explicit or partial specialization of any member class template of a standard
library class or class template.
.UNINDENT
.sp
Examples:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
namespace std {
int x; // warning: modification of \(aqstd\(aq namespace can result in undefined behavior [bugprone\-dont\-modify\-std\-namespace]
}
namespace posix::a { // warning: modification of \(aqposix\(aq namespace can result in undefined behavior
}
template <>
struct ::std::hash { // warning: modification of \(aqstd\(aq 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 \(aqstd\(aq namespace can result in undefined behavior
template <>
bool less::operator()(MyData &&, MyData &&) const { // warning: modification of \(aqstd\(aq namespace can result in undefined behavior
return true;
}
}
.EE
.UNINDENT
.UNINDENT
.SS References
.sp
This check corresponds to the CERT C++ Coding Standard rule
DCL58\-CPP. Do not modify the standard namespaces \%\&.
.SS bugprone\-string\-constructor
.sp
Finds string constructors that are suspicious and probably errors.
.sp
A common mistake is to swap parameters to the \(aqfill\(aq string\-constructor.
.sp
Examples:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
std::string str(\(aqx\(aq, 50); // should be str(50, \(aqx\(aq)
.EE
.UNINDENT
.UNINDENT
.sp
Calling the string\-literal constructor with a length bigger than the literal is
suspicious and adds extra random characters to the string.
.sp
Examples:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
std::string(\(dqtest\(dq, 200); // Will include random characters after \(dqtest\(dq.
std::string(\(dqtest\(dq, 2, 5); // Will include random characters after \(dqst\(dq.
std::string_view(\(dqtest\(dq, 200);
.EE
.UNINDENT
.UNINDENT
.sp
Creating an empty string from constructors with parameters is considered
suspicious. The programmer should use the empty constructor instead.
.sp
Examples:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
std::string(\(dqtest\(dq, 0); // Creation of an empty string.
std::string(\(dqtest\(dq, 1, 0);
std::string_view(\(dqtest\(dq, 0);
.EE
.UNINDENT
.UNINDENT
.sp
Passing an invalid first character position parameter to constructor will
cause \fBstd::out_of_range\fP exception at runtime.
.sp
Examples:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
std::string(\(dqtest\(dq, \-1, 10); // Negative first character position.
std::string(\(dqtest\(dq, 10, 10); // First character position is bigger than string literal character range\(dq.
.EE
.UNINDENT
.UNINDENT
.SS Options
.INDENT 0.0
.TP
.B WarnOnLargeLength
When \fItrue\fP, the check will warn on a string with a length greater than
\fBLargeLengthThreshold\fP\&. Default is \fItrue\fP\&.
.UNINDENT
.INDENT 0.0
.TP
.B LargeLengthThreshold
An integer specifying the large length threshold. Default is \fI0x800000\fP\&.
.UNINDENT
.INDENT 0.0
.TP
.B StringNames
Default is \fI::std::basic_string;::std::basic_string_view\fP\&.
.sp
Semicolon\-delimited list of class names to apply this check to.
By default \fI::std::basic_string\fP applies to \fBstd::string\fP and
\fBstd::wstring\fP\&. Set to e.g. \fI::std::basic_string;llvm::StringRef;QString\fP
to perform this check on custom classes.
.UNINDENT
.SS bugprone\-string\-integer\-assignment
.sp
The check finds assignments of an integer to \fBstd::basic_string\fP
(\fBstd::string\fP, \fBstd::wstring\fP, etc.). The source of the problem is the
following assignment operator of \fBstd::basic_string\fP:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
basic_string& operator=( CharT ch );
.EE
.UNINDENT
.UNINDENT
.sp
Numeric types can be implicitly casted to character types.
.INDENT 0.0
.INDENT 3.5
.sp
.EX
std::string s;
int x = 5965;
s = 6;
s = x;
.EE
.UNINDENT
.UNINDENT
.sp
Use the appropriate conversion functions or character literals.
.INDENT 0.0
.INDENT 3.5
.sp
.EX
std::string s;
int x = 5965;
s = \(aq6\(aq;
s = std::to_string(x);
.EE
.UNINDENT
.UNINDENT
.sp
In order to suppress false positives, use an explicit cast.
.INDENT 0.0
.INDENT 3.5
.sp
.EX
std::string s;
s = static_cast(6);
.EE
.UNINDENT
.UNINDENT
.SS bugprone\-string\-literal\-with\-embedded\-nul
.sp
Finds occurrences of string literal with embedded NUL character and validates
their usage.
.SS Invalid escaping
.sp
Special characters can be escaped within a string literal by using their
hexadecimal encoding like \fB\ex42\fP\&. A common mistake is to escape them
like this \fB\e0x42\fP where the \fB\e0\fP stands for the NUL character.
.INDENT 0.0
.INDENT 3.5
.sp
.EX
const char* Example[] = \(dqInvalid character: \e0x12 should be \ex12\(dq;
const char* Bytes[] = \(dq\ex03\e0x02\e0x01\e0x00\e0xFF\e0xFF\e0xFF\(dq;
.EE
.UNINDENT
.UNINDENT
.SS Truncated literal
.sp
String\-like classes can manipulate strings with embedded NUL as they are
keeping track of the bytes and the length. This is not the case for a
\fBchar*\fP (NUL\-terminated) string.
.sp
A common mistake is to pass a string\-literal with embedded NUL to a string
constructor expecting a NUL\-terminated string. The bytes after the first NUL
character are truncated.
.INDENT 0.0
.INDENT 3.5
.sp
.EX
std::string str(\(dqabc\e0def\(dq); // \(dqdef\(dq is truncated
str += \(dq\e0\(dq; // This statement is doing nothing
if (str == \(dq\e0abc\(dq) return; // This expression is always true
.EE
.UNINDENT
.UNINDENT
.SS bugprone\-stringview\-nullptr
.sp
Checks for various ways that the \fBconst CharT*\fP constructor of
\fBstd::basic_string_view\fP can be passed a null argument and replaces them
with the default constructor in most cases. For the comparison operators,
braced initializer list does not compile so instead a call to \fB\&.empty()\fP
or the empty string literal are used, where appropriate.
.sp
This prevents code from invoking behavior which is unconditionally undefined.
The single\-argument \fBconst CharT*\fP constructor does not check for the null
case before dereferencing its input. The standard is slated to add an
explicitly\-deleted overload to catch some of these cases: wg21.link/p2166
.sp
To catch the additional cases of \fBNULL\fP (which expands to \fB__null\fP) and
\fB0\fP, first run the \fBmodernize\-use\-nullptr\fP check to convert the callers to
\fBnullptr\fP\&.
.INDENT 0.0
.INDENT 3.5
.sp
.EX
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
.EE
.UNINDENT
.UNINDENT
.sp
is translated into...
.INDENT 0.0
.INDENT 3.5
.sp
.EX
std::string_view sv = {};
sv = {};
bool is_empty = sv.empty();
bool isnt_empty = !sv.empty();
accepts_sv(\(dq\(dq);
accepts_sv(\(dq\(dq); // A
accepts_sv({nullptr, 0}); // B
.EE
.UNINDENT
.UNINDENT
.sp
\fBNote:\fP
.INDENT 0.0
.INDENT 3.5
The source pattern with trailing comment \(dqA\(dq selects the \fB(const CharT*)\fP
constructor overload and then value\-initializes the pointer, causing a null
dereference. It happens to not include the \fBnullptr\fP literal, but it is
still within the scope of this ClangTidy check.
.UNINDENT
.UNINDENT
.sp
\fBNote:\fP
.INDENT 0.0
.INDENT 3.5
The source pattern with trailing comment \(dqB\(dq selects the
\fB(const CharT*, size_type)\fP constructor which is perfectly valid, since the
length argument is \fB0\fP\&. It is not changed by this ClangTidy check.
.UNINDENT
.UNINDENT
.SS bugprone\-suspicious\-enum\-usage
.sp
The checker detects various cases when an enum is probably misused
(as a bitmask).
.INDENT 0.0
.IP 1. 3
When \(dqADD\(dq or \(dqbitwise OR\(dq is used between two enum which come
from different types and these types value ranges are not disjoint.
.UNINDENT
.sp
The following cases will be investigated only using \fBStrictMode\fP \%<#\:cmdoption-arg-StrictMode>\&. We
regard the enum as a (suspicious)
bitmask if the three conditions below are true at the same time:
.INDENT 0.0
.IP \(bu 2
at most half of the elements of the enum are non pow\-of\-2 numbers (because of
short enumerations)
.IP \(bu 2
there is another non pow\-of\-2 number than the enum constant representing all
choices (the result \(dqbitwise OR\(dq operation of all enum elements)
.IP \(bu 2
enum type variable/enumconstant is used as an argument of a \fI+\fP or \(dqbitwise
OR\(dq operator
.UNINDENT
.sp
So whenever the non pow\-of\-2 element is used as a bitmask element we diagnose a
misuse and give a warning.
.INDENT 0.0
.IP 2. 3
Investigating the right hand side of \fB+=\fP and \fB|=\fP operator.
.IP 3. 3
Check only the enum value side of a \fB|\fP and \fB+\fP operator if one of
them is not enum val.
.IP 4. 3
Check both side of \fB|\fP or \fB+\fP operator where the enum values are from
the same enum type.
.UNINDENT
.sp
Examples:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
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.
.EE
.UNINDENT
.UNINDENT
.SS Options
.INDENT 0.0
.TP
.B StrictMode
Default value: 0.
When non\-null the suspicious bitmask usage will be investigated additionally
to the different enum usage check.
.UNINDENT
.SS bugprone\-suspicious\-include
.sp
The check detects various cases when an include refers to what appears to be an
implementation file, which often leads to hard\-to\-track\-down ODR violations.
.sp
Examples:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
#include \(dqDinosaur.hpp\(dq // OK, .hpp files tend not to have definitions.
#include \(dqPterodactyl.h\(dq // OK, .h files tend not to have definitions.
#include \(dqVelociraptor.cpp\(dq // Warning, filename is suspicious.
#include_next // Warning, filename is suspicious.
.EE
.UNINDENT
.UNINDENT
.SS Options
.INDENT 0.0
.TP
.B IgnoredRegex
A regular expression for the file name to be ignored by the check. Default
is empty string.
.UNINDENT
.SS bugprone\-suspicious\-memory\-comparison
.sp
Finds potentially incorrect calls to \fBmemcmp()\fP based on properties of the
arguments. The following cases are covered:
.sp
\fBCase 1: Non\-standard\-layout type\fP
.sp
Comparing the object representations of non\-standard\-layout objects may not
properly compare the value representations.
.sp
\fBCase 2: Types with no unique object representation\fP
.sp
Objects with the same value may not have the same object representation.
This may be caused by padding or floating\-point types.
.sp
See also:
EXP42\-C. Do not compare padding data \%
and
FLP37\-C. Do not use object representations to compare floating\-point values \%
.sp
This check is also related to and partially overlaps the CERT C++ Coding Standard rules
OOP57\-CPP. Prefer special member functions and overloaded operators to
C Standard Library functions \%
and
EXP62\-CPP. Do not access the bits of an object representation that are not
part of the object\(aqs value representation \%
.sp
\fIcert\-exp42\-c\fP redirects here as an alias of this check.
.SS bugprone\-suspicious\-memset\-usage
.sp
This check finds \fBmemset()\fP calls with potential mistakes in their arguments.
Considering the function as \fBvoid* memset(void* destination, int fill_value,
size_t byte_count)\fP, the following cases are covered:
.sp
\fBCase 1: Fill value is a character \(ga\(ga\(aq0\(aq\(ga\(ga\fP
.sp
Filling up a memory area with ASCII code 48 characters is not customary,
possibly integer zeroes were intended instead.
The check offers a replacement of \fB\(aq0\(aq\fP with \fB0\fP\&. Memsetting character
pointers with \fB\(aq0\(aq\fP is allowed.
.sp
\fBCase 2: Fill value is truncated\fP
.sp
Memset converts \fBfill_value\fP to \fBunsigned char\fP before using it. If
\fBfill_value\fP is out of unsigned character range, it gets truncated
and memory will not contain the desired pattern.
.sp
\fBCase 3: Byte count is zero\fP
.sp
Calling memset with a literal zero in its \fBbyte_count\fP argument is likely
to be unintended and swapped with \fBfill_value\fP\&. The check offers to swap
these two arguments.
.sp
Corresponding cpplint.py check name: \fBruntime/memset\fP\&.
.sp
Examples:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
void foo() {
int i[5] = {1, 2, 3, 4, 5};
int *ip = i;
char c = \(aq1\(aq;
char *cp = &c;
int v = 0;
// Case 1
memset(ip, \(aq0\(aq, 1); // suspicious
memset(cp, \(aq0\(aq, 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
}
.EE
.UNINDENT
.UNINDENT
.SS bugprone\-suspicious\-missing\-comma
.sp
String literals placed side\-by\-side are concatenated at translation phase 6
(after the preprocessor). This feature is used to represent long string
literal on multiple lines.
.sp
For instance, the following declarations are equivalent:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
const char* A[] = \(dqThis is a test\(dq;
const char* B[] = \(dqThis\(dq \(dq is a \(dq \(dqtest\(dq;
.EE
.UNINDENT
.UNINDENT
.sp
A common mistake done by programmers is to forget a comma between two string
literals in an array initializer list.
.INDENT 0.0
.INDENT 3.5
.sp
.EX
const char* Test[] = {
\(dqline 1\(dq,
\(dqline 2\(dq // Missing comma!
\(dqline 3\(dq,
\(dqline 4\(dq,
\(dqline 5\(dq
};
.EE
.UNINDENT
.UNINDENT
.sp
The array contains the string \(dqline 2line3\(dq at offset 1 (i.e. Test[1]). Clang
won\(aqt generate warnings at compile time.
.sp
This check may warn incorrectly on cases like:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
const char* SupportedFormat[] = {
\(dqError %s\(dq,
\(dqCode \(dq PRIu64, // May warn here.
\(dqWarning %s\(dq,
};
.EE
.UNINDENT
.UNINDENT
.SS Options
.INDENT 0.0
.TP
.B SizeThreshold
An unsigned integer specifying the minimum size of a string literal to be
considered by the check. Default is \fB5U\fP\&.
.UNINDENT
.INDENT 0.0
.TP
.B RatioThreshold
A string specifying the maximum threshold ratio [0, 1.0] of suspicious string
literals to be considered. Default is \fB\(dq.2\(dq\fP\&.
.UNINDENT
.INDENT 0.0
.TP
.B MaxConcatenatedTokens
An unsigned integer specifying the maximum number of concatenated tokens.
Default is \fB5U\fP\&.
.UNINDENT
.SS bugprone\-suspicious\-realloc\-usage
.sp
This check finds usages of \fBrealloc\fP where the return value is assigned to
the same expression as passed to the first argument:
\fBp = realloc(p, size);\fP
The problem with this construct is that if \fBrealloc\fP fails it returns a
null pointer but does not deallocate the original memory. If no other variable
is pointing to it, the original memory block is not available any more for the
program to use or free. In either case \fBp = realloc(p, size);\fP indicates bad
coding style and can be replaced by \fBq = realloc(p, size);\fP\&.
.sp
The pointer expression (used at \fBrealloc\fP) can be a variable or a field
member of a data structure, but can not contain function calls or unresolved
types.
.sp
In obvious cases when the pointer used at realloc is assigned to another
variable before the \fBrealloc\fP call, no warning is emitted. This happens only
if a simple expression in form of \fBq = p\fP or \fBvoid *q = p\fP is found in the
same function where \fBp = realloc(p, ...)\fP is found. The assignment has to be
before the call to realloc (but otherwise at any place) in the same function.
This suppression works only if \fBp\fP is a single variable.
.sp
Examples:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
struct A {
void *p;
};
A &getA();
void foo(void *p, A *a, int new_size) {
p = realloc(p, new_size); // warning: \(aqp\(aq may be set to null if \(aqrealloc\(aq fails, which may result in a leak of the original buffer
a\->p = realloc(a\->p, new_size); // warning: \(aqa\->p\(aq may be set to null if \(aqrealloc\(aq 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
}
.EE
.UNINDENT
.UNINDENT
.SS bugprone\-suspicious\-semicolon
.sp
Finds most instances of stray semicolons that unexpectedly alter the meaning of
the code. More specifically, it looks for \fBif\fP, \fBwhile\fP, \fBfor\fP and
\fBfor\-range\fP statements whose body is a single semicolon, and then analyzes
the context of the code (e.g. indentation) in an attempt to determine whether
that is intentional.
.INDENT 0.0
.INDENT 3.5
.sp
.EX
if (x < y);
{
x++;
}
.EE
.UNINDENT
.UNINDENT
.sp
Here the body of the \fBif\fP statement consists of only the semicolon at the end
of the first line, and \fIx\fP will be incremented regardless of the condition.
.INDENT 0.0
.INDENT 3.5
.sp
.EX
while ((line = readLine(file)) != NULL);
processLine(line);
.EE
.UNINDENT
.UNINDENT
.sp
As a result of this code, \fIprocessLine()\fP will only be called once, when the
\fBwhile\fP loop with the empty body exits with \fBline == NULL\fP\&. The indentation
of the code indicates the intention of the programmer.
.INDENT 0.0
.INDENT 3.5
.sp
.EX
if (x >= y);
x \-= y;
.EE
.UNINDENT
.UNINDENT
.sp
While the indentation does not imply any nesting, there is simply no valid
reason to have an \fIif\fP statement with an empty body (but it can make sense for
a loop). So this check issues a warning for the code above.
.sp
To solve the issue remove the stray semicolon or in case the empty body is
intentional, reflect this using code indentation or put the semicolon in a new
line. For example:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
while (readWhitespace());
Token t = readNextToken();
.EE
.UNINDENT
.UNINDENT
.sp
Here the second line is indented in a way that suggests that it is meant to be
the body of the \fIwhile\fP loop \- whose body is in fact empty, because of the
semicolon at the end of the first line.
.sp
Either remove the indentation from the second line:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
while (readWhitespace());
Token t = readNextToken();
.EE
.UNINDENT
.UNINDENT
.sp
\&... or move the semicolon from the end of the first line to a new line:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
while (readWhitespace())
;
Token t = readNextToken();
.EE
.UNINDENT
.UNINDENT
.sp
In this case the check will assume that you know what you are doing, and will
not raise a warning.
.SS bugprone\-suspicious\-string\-compare
.sp
Find suspicious usage of runtime string comparison functions.
This check is valid in C and C++.
.sp
Checks for calls with implicit comparator and proposed to explicitly add it.
.INDENT 0.0
.INDENT 3.5
.sp
.EX
if (strcmp(...)) // Implicitly compare to zero
if (!strcmp(...)) // Won\(aqt warn
if (strcmp(...) != 0) // Won\(aqt warn
.EE
.UNINDENT
.UNINDENT
.sp
Checks that compare function results (i.e., \fBstrcmp\fP) are compared to valid
constant. The resulting value is
.INDENT 0.0
.INDENT 3.5
.sp
.EX
< 0 when lower than,
> 0 when greater than,
== 0 when equals.
.EE
.UNINDENT
.UNINDENT
.sp
A common mistake is to compare the result to \fI1\fP or \fI\-1\fP\&.
.INDENT 0.0
.INDENT 3.5
.sp
.EX
if (strcmp(...) == \-1) // Incorrect usage of the returned value.
.EE
.UNINDENT
.UNINDENT
.sp
Additionally, the check warns if the results value is implicitly cast to a
\fIsuspicious\fP non\-integer type. It\(aqs happening when the returned value is
used in a wrong context.
.INDENT 0.0
.INDENT 3.5
.sp
.EX
if (strcmp(...) < 0.) // Incorrect usage of the returned value.
.EE
.UNINDENT
.UNINDENT
.SS Options
.INDENT 0.0
.TP
.B WarnOnImplicitComparison
When \fItrue\fP, the check will warn on implicit comparison. \fItrue\fP by default.
.UNINDENT
.INDENT 0.0
.TP
.B WarnOnLogicalNotComparison
When \fItrue\fP, the check will warn on logical not comparison. \fIfalse\fP by default.
.UNINDENT
.INDENT 0.0
.TP
.B StringCompareLikeFunctions
A string specifying the comma\-separated names of the extra string comparison
functions. Default is an empty string.
The check will detect the following string comparison functions:
\fI__builtin_memcmp\fP, \fI__builtin_strcasecmp\fP, \fI__builtin_strcmp\fP,
\fI__builtin_strncasecmp\fP, \fI__builtin_strncmp\fP, \fI_mbscmp\fP, \fI_mbscmp_l\fP,
\fI_mbsicmp\fP, \fI_mbsicmp_l\fP, \fI_mbsnbcmp\fP, \fI_mbsnbcmp_l\fP, \fI_mbsnbicmp\fP,
\fI_mbsnbicmp_l\fP, \fI_mbsncmp\fP, \fI_mbsncmp_l\fP, \fI_mbsnicmp\fP, \fI_mbsnicmp_l\fP,
\fI_memicmp\fP, \fI_memicmp_l\fP, \fI_stricmp\fP, \fI_stricmp_l\fP, \fI_strnicmp\fP,
\fI_strnicmp_l\fP, \fI_wcsicmp\fP, \fI_wcsicmp_l\fP, \fI_wcsnicmp\fP, \fI_wcsnicmp_l\fP,
\fIlstrcmp\fP, \fIlstrcmpi\fP, \fImemcmp\fP, \fImemicmp\fP, \fIstrcasecmp\fP, \fIstrcmp\fP,
\fIstrcmpi\fP, \fIstricmp\fP, \fIstrncasecmp\fP, \fIstrncmp\fP, \fIstrnicmp\fP, \fIwcscasecmp\fP,
\fIwcscmp\fP, \fIwcsicmp\fP, \fIwcsncmp\fP, \fIwcsnicmp\fP, \fIwmemcmp\fP\&.
.UNINDENT
.SS bugprone\-suspicious\-stringview\-data\-usage
.sp
Identifies suspicious usages of \fBstd::string_view::data()\fP that could lead to
reading out\-of\-bounds data due to inadequate or incorrect string null
termination.
.sp
It warns when the result of \fBdata()\fP is passed to a constructor or function
without also passing the corresponding result of \fBsize()\fP or \fBlength()\fP
member function. Such usage can lead to unintended behavior, particularly when
assuming the data pointed to by \fBdata()\fP is null\-terminated.
.sp
The absence of a \fBc_str()\fP method in \fBstd::string_view\fP often leads
developers to use \fBdata()\fP as a substitute, especially when interfacing with
C APIs that expect null\-terminated strings. However, since \fBdata()\fP does not
guarantee null termination, this can result in unintended behavior if the API
relies on proper null termination for correct string interpretation.
.sp
In today\(aqs programming landscape, this scenario can occur when implicitly
converting an \fBstd::string_view\fP to an \fBstd::string\fP\&. Since the constructor
in \fBstd::string\fP designed for string\-view\-like objects is \fBexplicit\fP,
attempting to pass an \fBstd::string_view\fP to a function expecting an
\fBstd::string\fP will result in a compilation error. As a workaround, developers
may be tempted to utilize the \fB\&.data()\fP method to achieve compilation,
introducing potential risks.
.sp
For instance:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
void printString(const std::string& str) {
std::cout << \(dqString: \(dq << str << std::endl;
}
void something(std::string_view sv) {
printString(sv.data());
}
.EE
.UNINDENT
.UNINDENT
.sp
In this example, directly passing \fBsv\fP to the \fBprintString\fP function would
lead to a compilation error due to the explicit nature of the \fBstd::string\fP
constructor. Consequently, developers might opt for \fBsv.data()\fP to resolve the
compilation error, albeit introducing potential hazards as discussed.
.SS Options
.INDENT 0.0
.TP
.B StringViewTypes
Option allows users to specify custom string view\-like types for analysis. It
accepts a semicolon\-separated list of type names or regular expressions
matching these types. Default value is:
\fI::std::basic_string_view;::llvm::StringRef\fP\&.
.UNINDENT
.INDENT 0.0
.TP
.B AllowedCallees
Specifies methods, functions, or classes where the result of \fB\&.data()\fP is
passed to. Allows to exclude such calls from the analysis. Accepts a
semicolon\-separated list of names or regular expressions matching these
entities. Default value is: empty string.
.UNINDENT
.SS bugprone\-swapped\-arguments
.sp
Finds potentially swapped arguments by examining implicit conversions.
It analyzes the types of the arguments being passed to a function and compares
them to the expected types of the corresponding parameters. If there is a
mismatch or an implicit conversion that indicates a potential swap, a warning
is raised.
.INDENT 0.0
.INDENT 3.5
.sp
.EX
void printNumbers(int a, float b);
int main() {
// Swapped arguments: float passed as int, int as float)
printNumbers(10.0f, 5);
return 0;
}
.EE
.UNINDENT
.UNINDENT
.sp
Covers a wide range of implicit conversions, including:
\- User\-defined conversions
\- Conversions from floating\-point types to boolean or integral types
\- Conversions from integral types to boolean or floating\-point types
\- Conversions from boolean to integer types or floating\-point types
\- Conversions from (member) pointers to boolean
.sp
It is important to note that for most argument swaps, the types need to match
exactly. However, there are exceptions to this rule. Specifically, when the
swapped argument is of integral type, an exact match is not always necessary.
Implicit casts from other integral types are also accepted. Similarly, when
dealing with floating\-point arguments, implicit casts between different
floating\-point types are considered acceptable.
.sp
To avoid confusion, swaps where both swapped arguments are of integral types or
both are of floating\-point types do not trigger the warning. In such cases,
it\(aqs assumed that the developer intentionally used different integral or
floating\-point types and does not raise a warning. This approach prevents false
positives and provides flexibility in handling situations where varying
integral or floating\-point types are intentionally utilized.
.SS bugprone\-switch\-missing\-default\-case
.sp
Ensures that switch statements without default cases are flagged, focuses only
on covering cases with non\-enums where the compiler may not issue warnings.
.sp
Switch statements without a default case can lead to unexpected
behavior and incomplete handling of all possible cases. When a switch statement
lacks a default case, if a value is encountered that does not match any of the
specified cases, the switch statement will do nothing and the program will
continue execution without handling the value.
.sp
This check helps identify switch statements that are missing a default case,
allowing developers to ensure that all possible cases are handled properly.
Adding a default case allows for graceful handling of unexpected or unmatched
values, reducing the risk of program errors and unexpected behavior.
.sp
Example:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
// 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;
}
.EE
.UNINDENT
.UNINDENT
.sp
\fBNote:\fP
.INDENT 0.0
.INDENT 3.5
Enum types are already covered by compiler warnings (comes under \-Wswitch)
when a switch statement does not handle all enum values. This check focuses
on non\-enum types where the compiler warnings may not be present.
.UNINDENT
.UNINDENT
.sp
\fBSee also:\fP
.INDENT 0.0
.INDENT 3.5
The CppCoreGuideline ES.79 \%
provide guidelines on switch statements, including the recommendation to
always provide a default case.
.UNINDENT
.UNINDENT
.SS bugprone\-tagged\-union\-member\-count
.sp
Gives warnings for tagged unions, where the number of tags is
different from the number of data members inside the union.
.sp
A struct or a class is considered to be a tagged union if it has
exactly one union data member and exactly one enum data member and
any number of other data members that are neither unions or enums.
Furthermore, the types of the union and the enum members must
not come from system header files nor the \fBstd\fP namespace.
.sp
Example:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
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;
};
.EE
.UNINDENT
.UNINDENT
.sp
The following example illustrates the exception for unions and enums from
system header files and the \fBstd\fP namespace.
.INDENT 0.0
.INDENT 3.5
.sp
.EX
#include
struct NotTaggedUnion {
enum MyEnum { MyEnumConstant1, MyEnumConstant2 } En;
pthread_mutex_t Mutex;
};
.EE
.UNINDENT
.UNINDENT
.sp
The \fBpthread_mutex_t\fP type may be defined as a union behind a \fBtypedef\fP,
in which case the check could mistake this type as a user\-defined tagged union.
After all, it has exactly one enum data member and exactly one union data member.
To avoid false\-positive cases originating from this, unions and enums from
system headers and the \fBstd\fP namespace are ignored when pinpointing the
union part and the enum part of a potential user\-defined tagged union.
.SS How enum constants are counted
.sp
The main complicating factor when counting the number of enum constants is that
some of them might be auxiliary values that purposefully don\(aqt have a
corresponding union data member and are used for something else. For example
the last enum constant sometimes explicitly \(dqpoints to\(dq the last declared valid
enum constant or tracks how many enum constants have been declared.
.sp
For an illustration:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
enum TagWithLast {
Tag1 = 0,
Tag2 = 1,
Tag3 = 2,
LastTag = 2
};
enum TagWithCounter {
Tag1, // is 0
Tag2, // is 1
Tag3, // is 2
TagCount, // is 3
};
.EE
.UNINDENT
.UNINDENT
.sp
The check counts the number of distinct values among the enum constants and not
the enum constants themselves. This way the enum constants that are essentially
just aliases of other enum constants are not included in the final count.
.sp
Handling of counting enum constants (ones like \fBTagCount\fP in the previous
code example) is done by decreasing the number of enum values by one if the name
of the last enum constant starts with a prefix or ends with a suffix specified in
\fBCountingEnumPrefixes\fP, \fBCountingEnumSuffixes\fP and it\(aqs value is
one less than the total number of distinct values in the enum.
.sp
When the final count is adjusted based on this heuristic then a diagnostic note
is emitted that shows which enum constant matched the criteria.
.sp
The heuristic can be disabled entirely (\fBEnableCountingEnumHeuristic\fP)
or configured to follow your naming convention (\fBCountingEnumPrefixes\fP,
\fBCountingEnumSuffixes\fP).
The strings specified in \fBCountingEnumPrefixes\fP,
\fBCountingEnumSuffixes\fP are matched case insensitively.
.sp
Example counts:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
// 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
};
.EE
.UNINDENT
.UNINDENT
.SS Options
.INDENT 0.0
.TP
.B EnableCountingEnumHeuristic
.UNINDENT
.sp
This option enables or disables the counting enum heuristic.
It uses the prefixes and suffixes specified in the options
\fBCountingEnumPrefixes\fP, \fBCountingEnumSuffixes\fP to find counting enum constants by
using them for prefix and suffix matching.
.sp
This option is enabled by default.
.sp
When \fBEnableCountingEnumHeuristic\fP is \fIfalse\fP:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
enum TagWithCounter {
Tag1,
Tag2,
Tag3,
TagCount,
};
struct TaggedUnion {
TagWithCounter Kind;
union {
int A;
long B;
char *Str;
float F;
} Data;
};
.EE
.UNINDENT
.UNINDENT
.sp
When \fBEnableCountingEnumHeuristic\fP is \fItrue\fP:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
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;
};
.EE
.UNINDENT
.UNINDENT
.INDENT 0.0
.TP
.B CountingEnumPrefixes
.UNINDENT
.sp
See \fBCountingEnumSuffixes\fP below.
.INDENT 0.0
.TP
.B CountingEnumSuffixes
.UNINDENT
.sp
CountingEnumPrefixes and CountingEnumSuffixes are lists of semicolon
separated strings that are used to search for possible counting enum constants.
These strings are matched case insensitively as prefixes and suffixes
respectively on the names of the enum constants.
If \fBEnableCountingEnumHeuristic\fP is \fIfalse\fP then these options do nothing.
.sp
The default value of \fBCountingEnumSuffixes\fP is \fIcount\fP and of
\fBCountingEnumPrefixes\fP is the empty string.
.sp
When \fBEnableCountingEnumHeuristic\fP is \fItrue\fP and
\fBCountingEnumSuffixes\fP is \fIcount;size\fP:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
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;
};
.EE
.UNINDENT
.UNINDENT
.sp
When \fBEnableCountingEnumHeuristic\fP is \fItrue\fP and
\fBCountingEnumPrefixes\fP is \fImaxsize;last_\fP
.INDENT 0.0
.INDENT 3.5
.sp
.EX
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;
};
.EE
.UNINDENT
.UNINDENT
.INDENT 0.0
.TP
.B StrictMode
.UNINDENT
.sp
When enabled, the check will also give a warning, when the number of tags
is greater than the number of union data members.
.sp
This option is disabled by default.
.sp
When \fBStrictMode\fP \%<#\:cmdoption-arg-StrictMode> is \fIfalse\fP:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
struct TaggedUnion {
enum {
Tag1,
Tag2,
Tag3,
} Tags;
union {
int I;
float F;
} Data;
};
.EE
.UNINDENT
.UNINDENT
.sp
When \fBStrictMode\fP \%<#\:cmdoption-arg-StrictMode> is \fItrue\fP:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
struct TaggedUnion { // warning: tagged union has fewer data members (2) than tags (3)
enum {
Tag1,
Tag2,
Tag3,
} Tags;
union {
int I;
float F;
} Data;
};
.EE
.UNINDENT
.UNINDENT
.SS bugprone\-terminating\-continue
.sp
Detects \fBdo while\fP loops with a condition always evaluating to false that
have a \fBcontinue\fP statement, as this \fBcontinue\fP terminates the loop
effectively.
.INDENT 0.0
.INDENT 3.5
.sp
.EX
void f() {
do {
// some code
continue; // terminating continue
// some other code
} while(false);
.EE
.UNINDENT
.UNINDENT
.SS bugprone\-throw\-keyword\-missing
.sp
Warns about a potentially missing \fBthrow\fP keyword. If a temporary object
is created, but the object\(aqs type derives from (or is the same as) a class
that has \(aqEXCEPTION\(aq, \(aqException\(aq or \(aqexception\(aq in its name, we can assume
that the programmer\(aqs intention was to throw that object.
.sp
Example:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
void f(int i) {
if (i < 0) {
// Exception is created but is not thrown.
std::runtime_error(\(dqUnexpected argument\(dq);
}
}
.EE
.UNINDENT
.UNINDENT
.SS bugprone\-throwing\-static\-initialization
.sp
Finds all \fBstatic\fP or \fBthread_local\fP variable declarations where the
initializer for the object may throw an exception.
.SS References
.sp
This check corresponds to the CERT C++ Coding Standard rule
ERR58\-CPP. Handle all exceptions thrown before main() begins executing \%\&.
.SS bugprone\-too\-small\-loop\-variable
.sp
Detects those \fBfor\fP loops that have a loop variable with a \(dqtoo small\(dq type
which means this type can\(aqt represent all values which are part of the
iteration range.
.INDENT 0.0
.INDENT 3.5
.sp
.EX
int main() {
long size = 294967296l;
for (short i = 0; i < size; ++i) {}
}
.EE
.UNINDENT
.UNINDENT
.sp
This \fBfor\fP loop is an infinite loop because the \fBshort\fP type can\(aqt
represent all values in the \fB[0..size]\fP interval.
.sp
In a real use case size means a container\(aqs size which depends on the
user input.
.INDENT 0.0
.INDENT 3.5
.sp
.EX
int doSomething(const std::vector& items) {
for (short i = 0; i < items.size(); ++i) {}
}
.EE
.UNINDENT
.UNINDENT
.sp
This algorithm works for a small amount of objects, but will lead to freeze for
a larger user input.
.sp
It\(aqs recommended to enable the compiler warning
\fI\-Wtautological\-constant\-out\-of\-range\-compare\fP as well, since check does
not inspect compile\-time constant loop boundaries to avoid overlaps with
the warning.
.SS Options
.INDENT 0.0
.TP
.B MagnitudeBitsUpperLimit
Upper limit for the magnitude bits of the loop variable. If it\(aqs set the check
filters out those catches in which the loop variable\(aqs type has more magnitude
bits as the specified upper limit. The default value is 16.
For example, if the user sets this option to 31 (bits), then a 32\-bit \fBunsigned int\fP
is ignored by the check, however a 32\-bit \fBint\fP is not (A 32\-bit \fBsigned int\fP
has 31 magnitude bits).
.UNINDENT
.INDENT 0.0
.INDENT 3.5
.sp
.EX
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
}
.EE
.UNINDENT
.UNINDENT
.SS bugprone\-unchecked\-optional\-access
.sp
\fINote\fP: This check uses a flow\-sensitive static analysis to produce its
results. Therefore, it may be more resource intensive (RAM, CPU) than the
average clang\-tidy check.
.sp
This check identifies unsafe accesses to values contained in
\fBstd::optional\fP, \fBabsl::optional\fP, \fBbase::Optional\fP,
\fBfolly::Optional\fP, \fBbsl::optional\fP, or
\fBBloombergLP::bdlb::NullableValue\fP objects. Below we will refer to all these
types collectively as \fBoptional\fP\&.
.sp
An access to the value of an \fBoptional\fP occurs when one of its \fBvalue\fP,
\fBoperator*\fP, or \fBoperator\->\fP member functions is invoked. To align with
common misconceptions, the check considers these member functions as
equivalent, even though there are subtle differences related to exceptions
versus undefined behavior. See \fIAdditional notes\fP, below, for more information
on this topic.
.sp
An access to the value of an \fBoptional\fP is considered safe if and only if
code in the local scope (for example, a function body) ensures that the
\fBoptional\fP has a value in all possible execution paths that can reach the
access. That should happen either through an explicit check, using the
\fBoptional::has_value\fP member function, or by constructing the
\fBoptional\fP in a way that shows that it unambiguously holds a value (e.g
using \fBstd::make_optional\fP which always returns a populated
\fBstd::optional\fP).
.sp
Below we list some examples, starting with unsafe optional access patterns,
followed by safe access patterns.
.SS Unsafe access patterns
.SS Access the value without checking if it exists
.sp
The check flags accesses to the value that are not locally guarded by
existence check:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
void f(std::optional opt) {
use(*opt); // unsafe: it is unclear whether \(gaopt\(ga has a value.
}
.EE
.UNINDENT
.UNINDENT
.SS Access the value in the wrong branch
.sp
The check is aware of the state of an optional object in different
branches of the code. For example:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
void f(std::optional opt) {
if (opt.has_value()) {
} else {
use(opt.value()); // unsafe: it is clear that \(gaopt\(ga does *not* have a value.
}
}
.EE
.UNINDENT
.UNINDENT
.SS Assume a function result to be stable
.sp
The check is aware that function results might not be stable. That is,
consecutive calls to the same function might return different values.
For example:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
void f(Foo foo) {
if (foo.take().has_value()) {
use(*foo.take()); // unsafe: it is unclear whether \(gafoo.take()\(ga has a value.
}
}
.EE
.UNINDENT
.UNINDENT
.SS Exception: accessor methods
.sp
The check assumes \fIaccessor\fP methods of a class are stable, with a heuristic to
determine which methods are accessors. Specifically, parameter\-free \fBconst\fP
methods and smart pointer\-like APIs (non \fBconst\fP overloads of \fB*\fP when
there is a parallel \fBconst\fP overload) are treated as accessors. Note that
this is not guaranteed to be safe \-\- but, it is widely used (safely) in
practice. Calls to non \fBconst\fP methods are assumed to modify the state of
the object and affect the stability of earlier accessor calls.
.SS Rely on invariants of uncommon APIs
.sp
The check is unaware of invariants of uncommon APIs. For example:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
void f(Foo foo) {
if (foo.HasProperty(\(dqbar\(dq)) {
use(*foo.GetProperty(\(dqbar\(dq)); // unsafe: it is unclear whether \(gafoo.GetProperty(\(dqbar\(dq)\(ga has a value.
}
}
.EE
.UNINDENT
.UNINDENT
.SS Check if a value exists, then pass the optional to another function
.sp
The check relies on local reasoning. The check and value access must
both happen in the same function. An access is considered unsafe even if
the caller of the function performing the access ensures that the
optional has a value. For example:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
void g(std::optional opt) {
use(*opt); // unsafe: it is unclear whether \(gaopt\(ga has a value.
}
void f(std::optional opt) {
if (opt.has_value()) {
g(opt);
}
}
.EE
.UNINDENT
.UNINDENT
.SS Safe access patterns
.SS Check if a value exists, then access the value
.sp
The check recognizes all straightforward ways for checking if a value
exists and accessing the value contained in an optional object. For
example:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
void f(std::optional opt) {
if (opt.has_value()) {
use(*opt);
}
}
.EE
.UNINDENT
.UNINDENT
.SS Check if a value exists, then access the value from a copy
.sp
The criteria that the check uses is semantic, not syntactic. It
recognizes when a copy of the optional object being accessed is known to
have a value. For example:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
void f(std::optional opt1) {
if (opt1.has_value()) {
std::optional opt2 = opt1;
use(*opt2);
}
}
.EE
.UNINDENT
.UNINDENT
.SS Ensure that a value exists using common macros
.sp
The check is aware of common macros like \fBCHECK\fP and \fBDCHECK\fP\&. Those can be
used to ensure that an optional object has a value. For example:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
void f(std::optional opt) {
DCHECK(opt.has_value());
use(*opt);
}
.EE
.UNINDENT
.UNINDENT
.SS Ensure that a value exists, then access the value in a correlated branch
.sp
The check is aware of correlated branches in the code and can figure out
when an optional object is ensured to have a value on all execution
paths that lead to an access. For example:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
void f(std::optional opt) {
bool safe = false;
if (opt.has_value() && SomeOtherCondition()) {
safe = true;
}
// ... more code...
if (safe) {
use(*opt);
}
}
.EE
.UNINDENT
.UNINDENT
.SS Stabilize function results
.sp
Function results are not assumed to be stable across calls, except for
const accessor methods. For more complex accessors (non\-const, or depend on
multiple params) it is best to store the result of the function call in a
local variable and use that variable to access the value. For example:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
void f(Foo foo) {
if (const auto& foo_opt = foo.take(); foo_opt.has_value()) {
use(*foo_opt);
}
}
.EE
.UNINDENT
.UNINDENT
.SS Do not rely on uncommon\-API invariants
.sp
When uncommon APIs guarantee that an optional has contents, do not rely on it
\-\- instead, check explicitly that the optional object has a value. For example:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
void f(Foo foo) {
if (const auto& property = foo.GetProperty(\(dqbar\(dq)) {
use(*property);
}
}
.EE
.UNINDENT
.UNINDENT
.sp
instead of the \fIHasProperty\fP, \fIGetProperty\fP pairing we saw above.
.SS Do not rely on caller\-performed checks
.sp
If you know that all of a function\(aqs callers have checked that an optional
argument has a value, either change the function to take the value directly or
check the optional again in the local scope of the callee. For example:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
void g(int val) {
use(val);
}
void f(std::optional opt) {
if (opt.has_value()) {
g(*opt);
}
}
.EE
.UNINDENT
.UNINDENT
.sp
and
.INDENT 0.0
.INDENT 3.5
.sp
.EX
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);
}
}
.EE
.UNINDENT
.UNINDENT
.SS Additional notes
.SS Aliases created via \fBusing\fP declarations
.sp
The check is aware of aliases of optional types that are created via
\fBusing\fP declarations. For example:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
using OptionalInt = std::optional;
void f(OptionalInt opt) {
use(opt.value()); // unsafe: it is unclear whether \(gaopt\(ga has a value.
}
.EE
.UNINDENT
.UNINDENT
.SS Lambdas
.sp
The check does not currently report unsafe optional accesses in lambdas.
A future version will expand the scope to lambdas, following the rules
outlined above. It is best to follow the same principles when using
optionals in lambdas.
.SS Access with \fBoperator*()\fP vs. \fBvalue()\fP
.sp
Given that \fBvalue()\fP has well\-defined behavior (either throwing an exception
or terminating the program), why treat it the same as \fBoperator*()\fP which
causes undefined behavior (UB)? That is, why is it considered unsafe to access
an optional with \fBvalue()\fP, if it\(aqs not provably populated with a value? For
that matter, why is \fBCHECK()\fP followed by \fBoperator*()\fP any better than
\fBvalue()\fP, given that they are semantically equivalent (on configurations
that disable exceptions)?
.sp
The answer is that we assume most users do not realize the difference between
\fBvalue()\fP and \fBoperator*()\fP\&. Shifting to \fBoperator*()\fP and some form of
explicit value\-presence check or explicit program termination has two
advantages:
.INDENT 0.0
.INDENT 3.5
.INDENT 0.0
.IP \(bu 2
Readability. The check, and any potential side effects like program
shutdown, are very clear in the code. Separating access from checks can
actually make the checks more obvious.
.IP \(bu 2
Performance. A single check can cover many or even all accesses within
scope. This gives the user the best of both worlds \-\- the safety of a
dynamic check, but without incurring redundant costs.
.UNINDENT
.UNINDENT
.UNINDENT
.SS Options
.INDENT 0.0
.TP
.B IgnoreSmartPointerDereference
If set to \fItrue\fP, the check ignores optionals that
are reached through overloaded smart\-pointer\-like dereference (\fBoperator*\fP,
\fBoperator\->\fP) on classes other than the optional type itself. This helps
avoid false positives where the analysis cannot equate results across such
calls. This does not cover access through \fBoperator[]\fP\&. Default is \fIfalse\fP\&.
.UNINDENT
.INDENT 0.0
.TP
.B IgnoreValueCalls
If set to \fItrue\fP, the check does not diagnose calls
to \fBoptional::value()\fP\&. Diagnostics for \fBoperator*()\fP and
\fBoperator\->()\fP remain enabled. This is useful for codebases that
intentionally rely on \fBvalue()\fP for defined, guarded access while still
flagging UB\-prone operator dereferences. Default is \fIfalse\fP\&.
.UNINDENT
.SS bugprone\-unchecked\-string\-to\-number\-conversion
.sp
This check flags calls to string\-to\-number conversion functions that do not
verify the validity of the conversion, such as \fBatoi()\fP or \fBscanf()\fP\&. It
does not flag calls to \fBstrtol()\fP, or other, related conversion functions
that do perform better error checking.
.INDENT 0.0
.INDENT 3.5
.sp
.EX
#include
void func(const char *buff) {
int si;
if (buff) {
si = atoi(buff); /* \(aqatoi\(aq used to convert a string to an integer, but function will
not report conversion errors; consider using \(aqstrtol\(aq instead. */
} else {
/* Handle error */
}
}
.EE
.UNINDENT
.UNINDENT
.SS References
.sp
This check corresponds to the CERT C Coding Standard rule
ERR34\-C. Detect errors when converting a string to a number \%\&.
.SS bugprone\-undefined\-memory\-manipulation
.sp
Finds calls of memory manipulation functions \fBmemset()\fP, \fBmemcpy()\fP and
\fBmemmove()\fP on non\-TriviallyCopyable objects resulting in undefined behavior.
.sp
Using memory manipulation functions on non\-TriviallyCopyable objects can lead
to a range of subtle and challenging issues in C++ code. The most immediate
concern is the potential for undefined behavior, where the state of the object
may become corrupted or invalid. This can manifest as crashes, data corruption,
or unexpected behavior at runtime, making it challenging to identify and
diagnose the root cause. Additionally, misuse of memory manipulation functions
can bypass essential object\-specific operations, such as constructors and
destructors, leading to resource leaks or improper initialization.
.sp
For example, when using \fBmemcpy\fP to copy \fBstd::string\fP, pointer data is
being copied, and it can result in a double free issue.
.INDENT 0.0
.INDENT 3.5
.sp
.EX
#include
#include
int main() {
std::string source = \(dqHello\(dq;
std::string destination;
std::memcpy(&destination, &source, sizeof(std::string));
// Undefined behavior may occur here, during std::string destructor call.
return 0;
}
.EE
.UNINDENT
.UNINDENT
.SS bugprone\-undelegated\-constructor
.sp
Finds creation of temporary objects in constructors that look like a
function call to another constructor of the same class.
.sp
The user most likely meant to use a delegating constructor or base class
initializer.
.SS bugprone\-unhandled\-exception\-at\-new
.sp
Finds calls to \fBnew\fP with missing exception handler for \fBstd::bad_alloc\fP\&.
.sp
Calls to \fBnew\fP may throw exceptions of type \fBstd::bad_alloc\fP that should
be handled. Alternatively, the nonthrowing form of \fBnew\fP can be
used. The check verifies that the exception is handled in the function
that calls \fBnew\fP\&.
.sp
If a nonthrowing version is used or the exception is allowed to propagate out
of the function no warning is generated.
.sp
The exception handler is checked if it catches a \fBstd::bad_alloc\fP or
\fBstd::exception\fP exception type, or all exceptions (catch\-all).
The check assumes that any user\-defined \fBoperator new\fP is either
\fBnoexcept\fP or may throw an exception of type \fBstd::bad_alloc\fP (or one
derived from it). Other exception class types are not taken into account.
.INDENT 0.0
.INDENT 3.5
.sp
.EX
int *f() noexcept {
int *p = new int[1000]; // warning: missing exception handler for allocation failure at \(aqnew\(aq
// ...
return p;
}
.EE
.UNINDENT
.UNINDENT
.INDENT 0.0
.INDENT 3.5
.sp
.EX
int *f1() { // not \(aqnoexcept\(aq
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: \(dqnothrow\(dq is used
// ...
return p;
}
.EE
.UNINDENT
.UNINDENT
.SS bugprone\-unhandled\-self\-assignment
.sp
\fIcert\-oop54\-cpp\fP redirects here as an alias for this check. For the CERT alias,
the \fIWarnOnlyIfThisHasSuspiciousField\fP option is set to \fIfalse\fP\&.
.sp
Finds user\-defined copy assignment operators which do not protect the code
against self\-assignment either by checking self\-assignment explicitly or
using the copy\-and\-swap or the copy\-and\-move method.
.sp
By default, this check searches only those classes which have any pointer or C
array field to avoid false positives. In case of a pointer or a C array, it\(aqs
likely that self\-copy assignment breaks the object if the copy assignment
operator was not written with care.
.sp
See also:
OOP54\-CPP. Gracefully handle self\-copy assignment \%
.sp
A copy assignment operator must prevent that self\-copy assignment ruins the
object state. A typical use case is when the class has a pointer field
and the copy assignment operator first releases the pointed object and
then tries to assign it:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
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;
}
};
.EE
.UNINDENT
.UNINDENT
.sp
There are two common C++ patterns to avoid this problem. The first is
the self\-assignment check:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
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;
}
};
.EE
.UNINDENT
.UNINDENT
.sp
The second one is the copy\-and\-swap method when we create a temporary copy
(using the copy constructor) and then swap this temporary object with \fBthis\fP:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
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;
}
};
.EE
.UNINDENT
.UNINDENT
.sp
There is a third pattern which is less common. Let\(aqs call it the copy\-and\-move
method when we create a temporary copy (using the copy constructor) and then move
this temporary object into \fBthis\fP (needs a move assignment operator):
.INDENT 0.0
.INDENT 3.5
.sp
.EX
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;
}
};
.EE
.UNINDENT
.UNINDENT
.SS Options
.INDENT 0.0
.TP
.B WarnOnlyIfThisHasSuspiciousField
When \fItrue\fP, the check will warn only if the container class of the copy
assignment operator has any suspicious fields (pointer, C array and C++ smart
pointer).
This option is set to \fItrue\fP by default.
.UNINDENT
.SS bugprone\-unintended\-char\-ostream\-output
.sp
Finds unintended character output from \fBunsigned char\fP and \fBsigned char\fP to
an \fBostream\fP\&.
.sp
Normally, when \fBunsigned char (uint8_t)\fP or \fBsigned char (int8_t)\fP is used,
it is more likely a number than a character. However, when it is passed
directly to \fBstd::ostream\fP\(aqs \fBoperator<<\fP, the result is the character
output instead of the numeric value. This often contradicts the developer\(aqs
intent to print integer values.
.INDENT 0.0
.INDENT 3.5
.sp
.EX
uint8_t v = 65;
std::cout << v; // output \(aqA\(aq instead of \(aq65\(aq
.EE
.UNINDENT
.UNINDENT
.sp
The check will suggest casting the value to an appropriate type to indicate the
intent, by default, it will cast to \fBunsigned int\fP for \fBunsigned char\fP and
\fBint\fP for \fBsigned char\fP\&.
.INDENT 0.0
.INDENT 3.5
.sp
.EX
std::cout << static_cast(v); // when v is unsigned char
std::cout << static_cast(v); // when v is signed char
.EE
.UNINDENT
.UNINDENT
.sp
To avoid lengthy cast statements, add prefix \fB+\fP to the variable can
also suppress warnings because unary expression will promote the value
to an \fBint\fP\&.
.INDENT 0.0
.INDENT 3.5
.sp
.EX
std::cout << +v;
.EE
.UNINDENT
.UNINDENT
.sp
Or cast to char to explicitly indicate that output should be a character.
.INDENT 0.0
.INDENT 3.5
.sp
.EX
std::cout << static_cast(v);
.EE
.UNINDENT
.UNINDENT
.SS Options
.INDENT 0.0
.TP
.B AllowedTypes
A semicolon\-separated list of type names that will be treated like the \fBchar\fP
type: the check will not report variables declared with with these types or
explicit cast expressions to these types. Note that this distinguishes type
aliases from the original type, so specifying e.g. \fBunsigned char\fP here
will not suppress reports about \fBuint8_t\fP even if it is defined as a
\fBtypedef\fP alias for \fBunsigned char\fP\&.
Default is \fIunsigned char;signed char\fP\&.
.UNINDENT
.INDENT 0.0
.TP
.B CastTypeName
When \fICastTypeName\fP is specified, the fix\-it will use \fICastTypeName\fP as the
cast target type. Otherwise, fix\-it will automatically infer the type.
.UNINDENT
.SS bugprone\-unique\-ptr\-array\-mismatch
.sp
Finds initializations of C++ unique pointers to non\-array type that are
initialized with an array.
.sp
If a pointer \fBstd::unique_ptr\fP is initialized with a new\-expression
\fBnew T[]\fP the memory is not deallocated correctly. A plain \fBdelete\fP is used
in this case to deallocate the target memory. Instead a \fBdelete[]\fP call is
needed. A \fBstd::unique_ptr\fP uses the correct delete operator. The check
does not emit warning if an \fBunique_ptr\fP with user\-specified deleter type is
used.
.sp
The check offers replacement of \fBunique_ptr\fP to \fBunique_ptr\fP if it
is used at a single variable declaration (one variable in one statement).
.sp
Example:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
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
};
.EE
.UNINDENT
.UNINDENT
.sp
This check partially covers the CERT C++ Coding Standard rule
MEM51\-CPP. Properly deallocate dynamically allocated resources \%
However, only the \fBstd::unique_ptr\fP case is detected by this check.
.SS bugprone\-unsafe\-functions
.sp
Checks for functions that have safer, more secure replacements available, or
are considered deprecated due to design flaws.
The check heavily relies on the functions from the
\fBAnnex K.\fP \(dqBounds\-checking interfaces\(dq of C11.
.INDENT 0.0
.TP
.B The check implements the following rules from the CERT C Coding Standard:
.INDENT 7.0
.IP \(bu 2
Recommendation MSC24\-C. Do not use deprecated or obsolescent functions \%\&.
.IP \(bu 2
Rule MSC33\-C. Do not pass invalid data to the asctime() function \%\&.
.UNINDENT
.UNINDENT
.sp
\fIcert\-msc24\-c\fP and \fIcert\-msc33\-c\fP redirect here as aliases of this check.
.SS Unsafe functions
.sp
The following functions are reported if \fBReportDefaultFunctions\fP
is enabled.
.sp
If \fIAnnex K.\fP is available, a replacement from \fIAnnex K.\fP is suggested for the
following functions:
.sp
\fBasctime\fP, \fBasctime_r\fP, \fBbsearch\fP, \fBctime\fP, \fBfopen\fP, \fBfprintf\fP,
\fBfreopen\fP, \fBfscanf\fP, \fBfwprintf\fP, \fBfwscanf\fP, \fBgetenv\fP, \fBgets\fP,
\fBgmtime\fP, \fBlocaltime\fP, \fBmbsrtowcs\fP, \fBmbstowcs\fP, \fBmemcpy\fP,
\fBmemmove\fP, \fBmemset\fP, \fBprintf\fP, \fBqsort\fP, \fBscanf\fP, \fBsnprintf\fP,
\fBsprintf\fP, \fBsscanf\fP, \fBstrcat\fP, \fBstrcpy\fP, \fBstrerror\fP, \fBstrlen\fP,
\fBstrncat\fP, \fBstrncpy\fP, \fBstrtok\fP, \fBswprintf\fP, \fBswscanf\fP, \fBvfprintf\fP,
\fBvfscanf\fP, \fBvfwprintf\fP, \fBvfwscanf\fP, \fBvprintf\fP, \fBvscanf\fP,
\fBvsnprintf\fP, \fBvsprintf\fP, \fBvsscanf\fP, \fBvswprintf\fP, \fBvswscanf\fP,
\fBvwprintf\fP, \fBvwscanf\fP, \fBwcrtomb\fP, \fBwcscat\fP, \fBwcscpy\fP,
\fBwcslen\fP, \fBwcsncat\fP, \fBwcsncpy\fP, \fBwcsrtombs\fP, \fBwcstok\fP, \fBwcstombs\fP,
\fBwctomb\fP, \fBwmemcpy\fP, \fBwmemmove\fP, \fBwprintf\fP, \fBwscanf\fP\&.
.sp
If \fIAnnex K.\fP is not available, replacements are suggested only for the
following functions from the previous list:
.INDENT 0.0
.INDENT 3.5
.INDENT 0.0
.IP \(bu 2
\fBasctime\fP, \fBasctime_r\fP, suggested replacement: \fBstrftime\fP
.IP \(bu 2
\fBgets\fP, suggested replacement: \fBfgets\fP
.UNINDENT
.UNINDENT
.UNINDENT
.sp
The following functions are always checked, regardless of \fIAnnex K\fP
availability:
.INDENT 0.0
.INDENT 3.5
.INDENT 0.0
.IP \(bu 2
\fBrewind\fP, suggested replacement: \fBfseek\fP
.IP \(bu 2
\fBsetbuf\fP, suggested replacement: \fBsetvbuf\fP
.UNINDENT
.UNINDENT
.UNINDENT
.sp
If \fBReportMoreUnsafeFunctions\fP is enabled,
the following functions are also checked:
.INDENT 0.0
.INDENT 3.5
.INDENT 0.0
.IP \(bu 2
\fBbcmp\fP, suggested replacement: \fBmemcmp\fP
.IP \(bu 2
\fBbcopy\fP, suggested replacement: \fBmemcpy_s\fP if \fIAnnex K\fP is available,
or \fBmemcpy\fP
.IP \(bu 2
\fBbzero\fP, suggested replacement: \fBmemset_s\fP if \fIAnnex K\fP is available,
or \fBmemset\fP
.IP \(bu 2
\fBgetpw\fP, suggested replacement: \fBgetpwuid\fP
.IP \(bu 2
\fBvfork\fP, suggested replacement: \fBposix_spawn\fP
.UNINDENT
.UNINDENT
.UNINDENT
.sp
Although mentioned in the associated CERT rules, the following functions are
\fBignored\fP by the check:
.sp
\fBatof\fP, \fBatoi\fP, \fBatol\fP, \fBatoll\fP, \fBtmpfile\fP\&.
.sp
The availability of \fIAnnex K\fP is determined based on the following macros:
.INDENT 0.0
.INDENT 3.5
.INDENT 0.0
.IP \(bu 2
\fB__STDC_LIB_EXT1__\fP: feature macro, which indicates the presence of
\fIAnnex K. \(dqBounds\-checking interfaces\(dq\fP in the library implementation
.IP \(bu 2
\fB__STDC_WANT_LIB_EXT1__\fP: user\-defined macro, which indicates that the
user requests the functions from \fIAnnex K.\fP to be defined.
.UNINDENT
.UNINDENT
.UNINDENT
.sp
Both macros have to be defined to suggest replacement functions from \fIAnnex K.\fP
\fB__STDC_LIB_EXT1__\fP is defined by the library implementation, and
\fB__STDC_WANT_LIB_EXT1__\fP must be defined to \fB1\fP by the user \fBbefore\fP
including any system headers.
.SS Custom functions
.sp
The option \fBCustomFunctions\fP allows the user to define custom functions
to be checked. The format is the following, without newlines:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
bugprone\-unsafe\-functions.CustomFunctions=\(dq
functionRegex1[, replacement1[, reason1]];
functionRegex2[, replacement2[, reason2]];
...
\(dq
.EE
.UNINDENT
.UNINDENT
.sp
The functions are matched using POSIX extended regular expressions.
\fI(Note: The regular expressions do not support negative\fP \fB(?!)\fP \fImatches.)\fP
.sp
The \fIreason\fP is optional and is used to provide additional information about
the reasoning behind the replacement. The default reason is
\fIis marked as unsafe\fP\&.
.sp
If \fIreplacement\fP is empty, the default text \fIit should not be used\fP will be
shown instead of the suggestion for a replacement.
.sp
If the \fIreason\fP starts with the character \fI>\fP, the reason becomes fully
custom. The default suffix is disabled even if a \fIreplacement\fP is present,
and only the reason message is shown after the matched function, to allow
better control over the suggestions. (The starting \fI>\fP and whitespace
directly after it are trimmed from the message.)
.sp
As an example, the following configuration matches only the function
\fBoriginal\fP in the default namespace. A similar diagnostic can also be printed
using a fully custom reason.
.INDENT 0.0
.INDENT 3.5
.sp
.EX
// bugprone\-unsafe\-functions.CustomFunctions:
// ^original$, replacement, is deprecated;
// Using the fully custom message syntax:
// ^suspicious$,,> should be avoided if possible.
original(); // warning: function \(aqoriginal\(aq is deprecated; \(aqreplacement\(aq should be used instead.
suspicious(); // warning: function \(aqsuspicious\(aq should be avoided if possible.
::std::original(); // no\-warning
original_function(); // no\-warning
.EE
.UNINDENT
.UNINDENT
.sp
If the regular expression contains the character \fI:\fP, it is matched against
the qualified name (i.e. \fBstd::original\fP), otherwise the regex is matched
against the unqualified name (\fBoriginal\fP). If the regular expression starts
with \fI::\fP (or \fI^::\fP), it is matched against the fully qualified name
(\fB::std::original\fP).
.sp
One of the use cases for fully custom messages is suggesting compiler options
and warning flags:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
// bugprone\-unsafe\-functions.CustomFunctions:
// ^memcpy$,,>is recommended to have compiler hardening using \(aq_FORTIFY_SOURCE\(aq;
// ^printf$,,>is recommended to have the \(aq\-Werror=format\-security\(aq compiler warning flag;
memcpy(dest, src, 999\(aq999); // warning: function \(aqmemcpy\(aq is recommended to have compiler hardening using \(aq_FORTIFY_SOURCE\(aq
printf(raw_str); // warning: function \(aqprintf\(aq is recommended to have the \(aq\-Werror=format\-security\(aq compiler warning flag
.EE
.UNINDENT
.UNINDENT
.sp
\fBNote:\fP
.INDENT 0.0
.INDENT 3.5
Fully qualified names can contain template parameters on certain C++ classes,
but not on C++ functions. Type aliases are resolved before matching.
.sp
As an example, the member function \fBopen\fP in the class \fBstd::ifstream\fP
has a fully qualified name of \fB::std::basic_ifstream::open\fP\&.
.sp
The example could also be matched with the regex
\fB::std::basic_ifstream<[^>]*>::open\fP, which matches all potential template
parameters, but does not match nested template classes.
.UNINDENT
.UNINDENT
.SS Options
.INDENT 0.0
.TP
.B ReportMoreUnsafeFunctions
When \fItrue\fP, additional functions from widely used APIs (such as POSIX) are
added to the list of reported functions.
See the main documentation of the check for the complete list as to what
this option enables.
Default is \fItrue\fP\&.
.UNINDENT
.INDENT 0.0
.TP
.B ReportDefaultFunctions
When \fItrue\fP, the check reports the default set of functions.
Consider changing the setting to false if you only want to see custom
functions matched via custom functions\&.
Default is \fItrue\fP\&.
.UNINDENT
.INDENT 0.0
.TP
.B CustomFunctions
A semicolon\-separated list of custom functions to be matched. A matched
function contains a regular expression, an optional name of the replacement
function, and an optional reason, separated by comma. For more information,
see Custom functions\&.
.UNINDENT
.SS Examples
.INDENT 0.0
.INDENT 3.5
.sp
.EX
#ifndef __STDC_LIB_EXT1__
#error \(dqAnnex K is not supported by the current standard library implementation.\(dq
#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[] = \(dqError: \(dq;
static const char Suffix[] = \(dq\en\(dq;
char Buf[BUFSIZE] = {0};
strcpy(Buf, Prefix); // warning: function \(aqstrcpy\(aq is not bounds\-checking; \(aqstrcpy_s\(aq should be used instead.
strcat(Buf, Msg); // warning: function \(aqstrcat\(aq is not bounds\-checking; \(aqstrcat_s\(aq should be used instead.
strcat(Buf, Suffix); // warning: function \(aqstrcat\(aq is not bounds\-checking; \(aqstrcat_s\(aq should be used instead.
if (fputs(buf, stderr) < 0) {
// error handling
return;
}
}
void UsingSafeFunctions(const char *Msg) {
static const char Prefix[] = \(dqError: \(dq;
static const char Suffix[] = \(dq\en\(dq;
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;
}
}
.EE
.UNINDENT
.UNINDENT
.SS bugprone\-unused\-local\-non\-trivial\-variable
.sp
Warns when a local non trivial variable is unused within a function.
The following types of variables are excluded from this check:
.INDENT 0.0
.IP \(bu 2
trivial and trivially copyable
.IP \(bu 2
references and pointers
.IP \(bu 2
exception variables in catch clauses
.IP \(bu 2
static or thread local
.IP \(bu 2
structured bindings
.IP \(bu 2
variables with \fB[[maybe_unused]]\fP attribute
.IP \(bu 2
name\-independent variables
.UNINDENT
.sp
This check can be configured to warn on all non\-trivial variables by setting
\fIIncludeTypes\fP to \fI\&.*\fP, and excluding specific types using \fIExcludeTypes\fP\&.
.sp
In the this example, \fImy_lock\fP would generate a warning that it is unused.
.INDENT 0.0
.INDENT 3.5
.sp
.EX
std::mutex my_lock;
// my_lock local variable is never used
.EE
.UNINDENT
.UNINDENT
.sp
In the next example, \fIfuture2\fP would generate a warning that it is unused.
.INDENT 0.0
.INDENT 3.5
.sp
.EX
std::future future1;
std::future future2;
// ...
MyObject foo = future1.get();
// future2 is not used.
.EE
.UNINDENT
.UNINDENT
.SS Options
.INDENT 0.0
.TP
.B IncludeTypes
Semicolon\-separated list of regular expressions matching types of variables
to check. By default the following types are checked:
.INDENT 7.0
.IP \(bu 2
\fI::std::.*mutex\fP
.IP \(bu 2
\fI::std::future\fP
.IP \(bu 2
\fI::std::basic_string\fP
.IP \(bu 2
\fI::std::basic_regex\fP
.IP \(bu 2
\fI::std::basic_istringstream\fP
.IP \(bu 2
\fI::std::basic_stringstream\fP
.IP \(bu 2
\fI::std::bitset\fP
.IP \(bu 2
\fI::std::filesystem::path\fP
.UNINDENT
.UNINDENT
.INDENT 0.0
.TP
.B ExcludeTypes
A semicolon\-separated list of regular expressions matching types that are
excluded from the \fIIncludeTypes\fP matches. By default it is an empty list.
.UNINDENT
.SS bugprone\-unused\-raii
.sp
Finds temporaries that look like RAII objects.
.sp
The canonical example for this is a scoped lock.
.INDENT 0.0
.INDENT 3.5
.sp
.EX
{
scoped_lock(&global_mutex);
critical_section();
}
.EE
.UNINDENT
.UNINDENT
.sp
The destructor of the scoped_lock is called before the \fBcritical_section\fP is
entered, leaving it unprotected.
.sp
We apply a number of heuristics to reduce the false positive count of this
check:
.INDENT 0.0
.IP \(bu 2
Ignore code expanded from macros. Testing frameworks make heavy use of this.
.IP \(bu 2
Ignore types with trivial destructors. They are very unlikely to be RAII
objects and there\(aqs no difference when they are deleted.
.IP \(bu 2
Ignore objects at the end of a compound statement (doesn\(aqt change behavior).
.IP \(bu 2
Ignore objects returned from a call.
.UNINDENT
.SS bugprone\-unused\-return\-value
.sp
Warns on unused function return values. The checked functions can be
configured.
.sp
Operator overloading with assignment semantics are ignored.
.SS Options
.INDENT 0.0
.TP
.B CheckedFunctions
Semicolon\-separated list of functions to check.
This parameter supports regexp. The function is checked if the name
and scope matches, with any arguments.
By default the following functions are checked:
\fB^::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$\fP
.INDENT 7.0
.IP \(bu 2
\fBstd::async()\fP\&. Not using the return value makes the call synchronous.
.IP \(bu 2
\fBstd::launder()\fP\&. Not using the return value usually means that the
function interface was misunderstood by the programmer. Only the returned
pointer is \(dqlaundered\(dq, not the argument.
.IP \(bu 2
\fBstd::remove()\fP, \fBstd::remove_if()\fP and \fBstd::unique()\fP\&. The returned
iterator indicates the boundary between elements to keep and elements to be
removed. Not using the return value means that the information about which
elements to remove is lost.
.IP \(bu 2
\fBstd::unique_ptr::release()\fP\&. Not using the return value can lead to
resource leaks if the same pointer isn\(aqt stored anywhere else. Often,
ignoring the \fBrelease()\fP return value indicates that the programmer
confused the function with \fBreset()\fP\&.
.IP \(bu 2
\fBstd::basic_string::empty()\fP and \fBstd::vector::empty()\fP\&. Not using the
return value often indicates that the programmer confused the function with
\fBclear()\fP\&.
.UNINDENT
.UNINDENT
.INDENT 0.0
.TP
.B CheckedReturnTypes
Semicolon\-separated list of function return types to check.
By default the following function return types are checked:
\fI^::std::error_code$\fP, \fI^::std::error_condition$\fP, \fI^::std::errc$\fP,
\fI^::std::expected$\fP, \fI^::boost::system::error_code$\fP
.UNINDENT
.INDENT 0.0
.TP
.B AllowCastToVoid
Controls whether casting return values to \fBvoid\fP is permitted. Default: \fIfalse\fP\&.
.UNINDENT
.sp
cert\-err33\-c \%<> is an alias of this check that checks a
fixed and large set of standard library functions.
.SS bugprone\-use\-after\-move
.sp
Warns if an object is used after it has been moved, for example:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
std::string str = \(dqHello, world!\en\(dq;
std::vector messages;
messages.emplace_back(std::move(str));
std::cout << str;
.EE
.UNINDENT
.UNINDENT
.sp
The last line will trigger a warning that \fBstr\fP is used after it has been
moved.
.sp
The check does not trigger a warning if the object is reinitialized after the
move and before the use. For example, no warning will be output for this code:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
messages.emplace_back(std::move(str));
str = \(dqGreetings, stranger!\en\(dq;
std::cout << str;
.EE
.UNINDENT
.UNINDENT
.sp
Subsections below explain more precisely what exactly the check considers to be
a move, use, and reinitialization.
.sp
The check takes control flow into account. A warning is only emitted if the use
can be reached from the move. This means that the following code does not
produce a warning:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
if (condition) {
messages.emplace_back(std::move(str));
} else {
std::cout << str;
}
.EE
.UNINDENT
.UNINDENT
.sp
On the other hand, the following code does produce a warning:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
for (int i = 0; i < 10; ++i) {
std::cout << str;
messages.emplace_back(std::move(str));
}
.EE
.UNINDENT
.UNINDENT
.sp
(The use\-after\-move happens on the second iteration of the loop.)
.sp
In some cases, the check may not be able to detect that two branches are
mutually exclusive. For example (assuming that \fBi\fP is an int):
.INDENT 0.0
.INDENT 3.5
.sp
.EX
if (i == 1) {
messages.emplace_back(std::move(str));
}
if (i == 2) {
std::cout << str;
}
.EE
.UNINDENT
.UNINDENT
.sp
In this case, the check will erroneously produce a warning, even though it is
not possible for both the move and the use to be executed. More formally, the
analysis is flow\-sensitive but not path\-sensitive \%\&.
.SS Silencing erroneous warnings
.sp
An erroneous warning can be silenced by reinitializing the object after the
move:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
if (i == 1) {
messages.emplace_back(std::move(str));
str = \(dq\(dq;
}
if (i == 2) {
std::cout << str;
}
.EE
.UNINDENT
.UNINDENT
.sp
If you want to avoid the overhead of actually reinitializing the object,
you can create a dummy function that causes the check to assume the object
was reinitialized:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
template
void IS_INITIALIZED(T&) {}
.EE
.UNINDENT
.UNINDENT
.sp
You can use this as follows:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
if (i == 1) {
messages.emplace_back(std::move(str));
}
if (i == 2) {
IS_INITIALIZED(str);
std::cout << str;
}
.EE
.UNINDENT
.UNINDENT
.sp
The check will not output a warning in this case because passing the object
to a function as a non\-const pointer or reference counts as a reinitialization
(see section Reinitialization below).
.SS Unsequenced moves, uses, and reinitializations
.sp
In many cases, C++ does not make any guarantees about the order in which
sub\-expressions of a statement are evaluated. This means that in code like the
following, it is not guaranteed whether the use will happen before or after the
move:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
void f(int i, std::vector v);
std::vector