You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
We can turn this on but I don't think any modern style uses functionCall(/*value=*/5) where void functionCall(int value)`.
bugprone-assert-side-effect ON
Recommend turning on as it will flag things like assert(++i = 5) or similar asserts where there are state modifications that would only be tracked in debug builds.
bugprone-assignment-in-if-condition ON
Detects things like if(i = 5) when meant to use if(i == 5).
bugprone-bad-signal-to-kill-thread ON
Prevents using pthread_kill(thread, SIGTERM); as this will stop the entire process, not just the thread.
bugprone-bool-pointer-implicit-conversion ON unless needed otherwise
I think leaving this on is a good idea as int *p = ...; if(p) {...} is more of a C-style approach.
bugprone-branch-clone ON
Prevents
if(thing)
x+=1;
...
else
...
x+=1;
Would flag x+=1 and anything else in both branches as repeated and can be manually moved out, reducing code.
bugprone-casting-through-void ON
Detects unsafe or redundant two-step casting operations involving void*
bugprone-chained-comparison ON
Prevents if(a < b < c) which really evaluates if ( (a<b)<c) when probably wanted if( (a<b) && (b<c))
bugprone-compare-pointer-to-member-virtual-function ON
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.
bugprone-copy-constructor-init ON
Finds copy constructors where the constructor doesn’t call the copy constructor of the base class.
bugprone-crtp-constructor-accessibility MAYBE
Detects error-prone Curiously Recurring Template Pattern usage, when the CRTP can be constructed outside itself and the derived class.
Unsure of this one and additional digging is needed
bugprone-dangling-handle ON
Detect dangling references in value handles like std::string_view
Ex:
vector<string_view> V;
V.push_back(string()); // V[0] is dangling.
bugprone-dynamic-static-initializers ON
intfoo() {
staticint k = bar();
return k;
}
Might have foo called twice by different threads simultaneously resulting in k being double initialized.
bugprone-easily-swappable-parameters MAYBE
This one can be tricky to handle in every case. For example:
voiddraw(int x, int y)
Could be refactored to use a point struct but this is potentially an externally visible API change that might not be possible.
auto a = {0.5f, 0.5f, 0.5f, 0.5f};
return std::accumulate(std::begin(a), std::end(a), 0);
Which mistakenly returns 0 because the operator+ will truncate each operation to int.
bugprone-forward-declaration-namespace ON
Prevents
namespacena { structA; }
namespacenb { structA {}; }
nb::A a;
// warning : no definition found for 'A', but a definition with the same name// 'A' found in another namespace 'nb::'
bugprone-forwarding-reference-overload ON
The check looks for perfect forwarding constructors that can hide copy or move constructors. (See Scott Meyers, Effective Modern C++, Item 26)
as (unsigned) row * (unsigned) col could be in the space of long instead of int. The fix isn't terible but there are possibly other gotchas in the fix process, especially if row and col are used in other contexts.
int i = 0;
// ...if (i++ < 5 && i > 0) {
// do something
}
bugprone-incorrect-enable-if ON
Detects incorrect usages of std::enable_if that don’t name the nested type type.
bugprone-incorrect-roundings ON
Prevents:
(int)(double_expression + 0.5)
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.
bugprone-infinite-loop ON
Prevents
int i = 0, j = 0;
while (i < 10) {
++j;
}
bugprone-integer-division ON
Prevents
floatfloatFunc(float);
intintFunc(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);
But does not warn on:
// OK, no integer division.
d = 32 * 8.0 / (2 + i);
d = 8 * floatFunc(1 + 7.0 / 2);
d = (double)i / (1 << 4);
// OK, there are signs of deliberateness.
d = 1 << (i / 2);
d = 9 + intFunc(6 * i / 32);
d = (int)(i / 32) - 8;
bugprone-lambda-function-name ON
Prevents
voidFancyFunction() {
[] { printf("Called from %s\n", __func__); }();
[] { printf("Now called from %s\n", __FUNCTION__); }();
}
as this outputs:
Called from operator()
Now called from operator()
bugprone-macro-parentheses ON
Prevents
#defineCUBE(X) (X) * (X) * (X)
int i = 3;
int a = 81 / CUBE(i);
->
int a = 81 / i * i * i;
->
int a = ((81 / i) * i) * i); /* Evaluates to 243 */
bugprone-macro-repeated-side-effects ON
Prevents
#definebadA(x,y) ((x)+((x)+(y))+(y))
ret = badA(a++, b);
bugprone-multi-level-implicit-pointer-conversion ON
Prevents
voidfoo(void* ptr);
intmain() {
int x = 42;
int* ptr = &x;
int** ptr_ptr = &ptr;
foo(ptr_ptr); // warning will trigger herereturn0;
}
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.
bugprone-multiple-new-in-one-expression ON
Prevents:
structA {
int Var;
};
structB {
B();
B(A *);
int Var;
};
structC {
int *X1;
int *X2;
};
voidf(A *, B *);
intf1(A *);
intf1(B *);
boolf2(A *);
voidfoo() {
A *PtrA;
B *PtrB;
try {
// Allocation of 'B'/'A' may fail after memory for 'A'/'B' was allocated.f(new A, new B); // warning: memory allocation may leak if an other allocation is sequenced after it and throws an exception; order of these allocations is undefined// List (aggregate) initialization is used.
C C1{newint, newint}; // no warning// Allocation of 'B'/'A' may fail after memory for 'A'/'B' was allocated but not yet passed to function 'f1'.int X = f1(new A) + f1(new B); // warning: memory allocation may leak if an other allocation is sequenced after it and throws an exception; order of these allocations is undefined// Allocation of 'B' may fail after memory for 'A' was allocated.// From C++17 on memory for 'B' is allocated first but still may leak if allocation of 'A' fails.
PtrB = newB(new A); // warning: memory allocation may leak if an other allocation is sequenced after it and throws an exception// 'new A' and 'new B' may be performed in any order.// 'new B'/'new A' may fail after memory for 'A'/'B' was allocated but not assigned to 'PtrA'/'PtrB'.
(PtrA = new A)->Var = (PtrB = new B)->Var; // warning: memory allocation may leak if an other allocation is sequenced after it and throws an exception; order of these allocations is undefined// Evaluation of 'f2(new A)' must be finished before 'f1(new B)' starts.// If 'new B' fails the allocated memory for 'A' is supposedly handled correctly because function 'f2' could take the ownership.bool Z = f2(new A) || f1(new B); // no warning
X = (f2(new A) ? f1(new A) : f1(new B)); // no warning// No warning if the result of both allocations is not passed to a function// or stored in a variable.
(new A)->Var = (new B)->Var; // no warning// No warning if at least one non-throwing allocation is used.f(new(std::nothrow) A, new B); // no warning
} catch(std::bad_alloc) {
}
// No warning if the allocation is outside a try block (or no catch handler exists for std::bad_alloc).// (The fact if exceptions can escape from 'foo' is not taken into account.)f(new A, new B); // no warning
}
bugprone-multiple-statement-macro ON
Prevents
#defineINCREMENT_TWO(x, y) (x)++; (y)++
if (do_increment)
INCREMENT_TWO(a, b); // (b)++ will be executed unconditionally.
#include<optional>voidprint(std::optional<int>);
intmain()
{
std::optional<int> opt;
// ...// Unintentional conversion from std::optional<int> to int and back to// std::optional<int>:print(opt.value());
// ...
}
becomes
#include<optional>voidprint(std::optional<int>);
intmain()
{
std::optional<int> opt;
// ...// Proposed code: Directly pass the std::optional<int> to the print// function.print(opt);
// ...
}
bugprone-parent-virtual-call ON
structA {
intvirtualfoo() {...}
};
structB: publicA {
intfoo() override {...}
};
structC: publicB {
intfoo() override { A::foo(); }
// ^^^^^^^^// warning: qualified name A::foo refers to a member overridden in subclass; did you mean 'B'? [bugprone-parent-virtual-call]
};
bugprone-posix-return ON
Flags if (posix_fadvise(...) < 0) {
and recommends changing the < to either = for success or > for failure
bugprone-redundant-branch-condition ON
Flags
bool onFire = isBurning();
if (onFire) {
if (onFire)
scream();
}
and
bool onFire = isBurning();
if (onFire) {
if (onFire && peopleInTheBuilding > 0)
scream();
}
but will fail to detect
int a = somethingReturning1();
int b = somethingReturning1();
if (peopleInTheBuilding == a) {
if (peopleInTheBuilding == b) {
doSomething();
}
}
bugprone-reserved-identifier ON
Checks for usages of identifiers reserved for use by the implementation.
Prevents
namespaceNS {
void__f(); // name is not allowed in user codeusing _Int = int; // same with this
#definecool__macro// also this
}
int_g(); // disallowed in global namespace only
bugprone-return-const-ref-from-parameter ON
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.
structS {
int v;
S(int);
~S();
};
const S &fn(const S &a) {
return a;
}
const S& s = fn(S{1});
s.v; // use after free
bugprone-shared-ptr-array-mismatch ON
Finds initializations of C++ shared pointers to non-array type that are initialized with an array.
If a shared pointer std::shared_ptr is initialized with a new-expression new T[] the memory is not deallocated correctly.
std::shared_ptr<Foo> x(new Foo[10]); // -> std::shared_ptr<Foo[]> x(new Foo[10]);// ^ warning: shared pointer to non-array is initialized with array [bugprone-shared-ptr-array-mismatch]
std::shared_ptr<Foo> x1(new Foo), x2(new Foo[10]); // no replacement// ^ warning: shared pointer to non-array is initialized with array [bugprone-shared-ptr-array-mismatch]
std::shared_ptr<Foo> x3(new Foo[10], [](const Foo *ptr) { delete[] ptr; }); // no warningstructS {
std::shared_ptr<Foo> x(new Foo[10]); // no replacement in this case// ^ warning: shared pointer to non-array is initialized with array [bugprone-shared-ptr-array-mismatch]
};
bugprone-signal-handler OFF
Finds specific constructs in signal handler functions that can cause undefined behavior. The rules for what is allowed differ between C++ language versions.
C++17 loosense restrictions thus this is harder to track and not effective (meaning the fix will still be problematic)
Currently, this check warns in the following cases: - signed char is assigned to an integer variable - signed char and unsigned char are compared with equality/inequality operator - signed char is converted to an integer in the array subscript
int IChar = EOF;
if (readChar(CChar)) {
IChar = CChar;
}
->
IChar = static_cast<unsignedchar>(CChar);
bugprone-sizeof-container ON
The check finds usages of sizeof on expressions of STL container types. Most likely the user wanted to use .size() instead.
std::string s;
int a = 47 + sizeof(s); // warning: sizeof() doesn't return the size of the container. Did you mean .size()?int b = sizeof(std::string); // no warning, probably intended.
std::string array_of_strings[10];
int c = sizeof(array_of_strings) / sizeof(array_of_strings[0]); // no warning, definitely intended.
std::array<int, 3> std_array;
int d = sizeof(std_array); // no warning, probably intended.
bugprone-sizeof-expression ON
The check finds usages of sizeof expressions which are most likely errors.
This noncompliant code example nests the call to wait() inside an if block and consequently fails to check the condition predicate after the notification is received. If the notification was spurious or malicious, the thread would wake up prematurely.
This compliant solution calls the wait() member function from within a while loop to check the condition both before and after the call to wait().
std::vector<int> v;
...
v.empty(); // Returns bool not used. Probably meant to clear.
->
v.clear(); // which returns void.
bugprone-string-constructor ON
std::string str('x', 50); // should be str(50, 'x')std::string("test", 200); // Will include random characters after "test".std::string_view("test", 200);
std::string("test", 0); // Creation of an empty string.std::string_view("test", 0);
bugprone-string-integer-assignment ON
std::string s;
int x = 5965;
s = 6;
s = x; // implicit cast to char which is unintended
->
s = std::to_string(x);
s = static_cast<char>(6); // or an explicit cast to supress false positives
bugprone-string-literal-with-embedded-nul ON
Flags:
constchar* Example[] = "Invalid character: \0x12 should be \x12";
constchar* Bytes[] = "\x03\0x02\0x01\0x00\0xFF\0xFF\0xFF";
// each \0 is interpreted as null
std::string str("abc\0def"); // "def" is truncated
str += "\0"; // This statement is doing nothingif (str == "\0abc") return; // This expression is always true
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.
bugprone-suspicious-include ON
Flags:
#include"Dinosaur.hpp"// OK, .hpp files tend not to have definitions.
#include"Pterodactyl.h"// OK, .h files tend not to have definitions.
#include"Velociraptor.cpp"// Warning, filename is suspicious.
#include_next <stdio.c> // Warning, filename is suspicious.
bugprone-suspicious-memory-comparison ON
Because std::memcmp() performs a bytewise comparison of the object representations, if the implementation uses a vtable pointer as part of the object representation, it will compare vtable pointers. If the dynamic type of either c1 or c2 is a derived class of type C, the comparison may fail despite the value representation of either object.
#include<cstring>classC {
int i;
public:virtualvoidf();
// ...
};
voidf(C &c1, C &c2) {
if (!std::memcmp(&c1, &c2, sizeof(C))) {
// ...
}
}
->
classC {
int i;
public:virtualvoidf();
booloperator==(const C &rhs) const {
return rhs.i == i;
}
// ...
};
voidf(C &c1, C &c2) {
if (c1 == c2) {
// ...
}
}
In this compliant solution, C defines an equality operator that is used instead of calling std::memcmp(). This solution ensures that only the value representation of the objects is considered when performing the comparison.
bugprone-suspicious-memset-usage ON
This check finds memset() calls with potential mistakes in their arguments.
voidfoo() {
int i[5] = {1, 2, 3, 4, 5};
int *ip = i;
char c = '1';
char *cp = &c;
int v = 0;
// Case 1memset(ip, '0', 1); // suspiciousmemset(cp, '0', 1); // OK// Case 2memset(ip, 0xabcd, 1); // fill value gets truncatedmemset(ip, 0x00, 1); // OK// Case 3memset(ip, sizeof(int), v); // zero length, potentially swappedmemset(ip, 0, 1); // OK
}
bugprone-suspicious-missing-comma ON
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.
constchar* Test[] = {
"line 1",
"line 2"// Missing comma!"line 3",
"line 4",
"line 5"
};
constchar* A[] = "This is a test"; // OKconstchar* B[] = "This"" is a ""test"; // Warns
bugprone-suspicious-realloc-usage ON
This check finds usages of realloc where the return value is assigned to the same expression as passed to the first argument: p = realloc(p, size); The problem with this construct is that if realloc fails it returns a null pointer but does not deallocate the original memory.
structA {
void *p;
};
A &getA();
voidfoo(void *p, A *a, int new_size) {
p = realloc(p, new_size); // warning: 'p' may be set to null if 'realloc' fails, which may result in a leak of the original buffer
a->p = realloc(a->p, new_size); // warning: 'a->p' may be set to null if 'realloc' fails, which may result in a leak of the original buffergetA().p = realloc(getA().p, new_size); // no warning
}
voidfoo1(void *p, int new_size) {
void *p1 = p;
p = realloc(p, new_size); // no warning
}
bugprone-suspicious-semicolon ON
Finds most instances of stray semicolons that unexpectedly alter the meaning of the code. More specifically, it looks for if, while, for and for-range statements whose body is a single semicolon, and then analyzes the context of the code (e.g. indentation) in an attempt to determine whether that is intentional.
if (x < y); // warns
{
x++;
}
while ((line = readLine(file)) != NULL); //warnsprocessLine(line);
if (x >= y); //warns
x -= y;
while (readWhitespace())
; // Does not warn as drastic unexpected change implies intended to do so
Token t = readNextToken();
bugprone-suspicious-string-compare ON
if (strcmp(...)) // Implicitly compare to zeroif (!strcmp(...)) // Won't warnif (strcmp(...) != 0) // Won't warnif (strcmp(...) == -1) // Incorrect usage of the returned value.if (strcmp(...) < 0.) // Incorrect usage of the returned value.
bugprone-suspicious-stringview-data-usage ON
Identifies suspicious usages of std::string_view::data() that could lead to reading out-of-bounds data due to inadequate or incorrect string null termination.
voidprintString(const std::string& str) {
std::cout << "String: " << str << std::endl;
}
voidsomething(std::string_view sv) {
printString(sv.data()); // warns of implicit casting of char* to string
}
-> printString(std::string(sv)); // Manually create a temporary string to be memory safe or...
-> voidprintString(const std::string_view& sv) // Change printString API to accept string_view directly.
bugprone-swapped-arguments ON (unless too many false positives)
Flags
voidprintNumbers(int a, float b);
intmain() {
// Swapped arguments: float passed as int, int as float)printNumbers(10.0f, 5);
return0;
}
bugprone-switch-missing-default-case ON
// Example 1:// warning: switching on non-enum value without default case may not cover all casesswitch (i) {
case0:
break;
}
// adding// default:// break;// fixes warning// Example 2:enum E { eE1 };
E e = eE1;
switch (e) { // no-warningcase eE1:
break;
}
bugprone-terminating-continue ON
voidf() {
do {
// some codecontinue; // warn: terminating continue// some other code
} while(false);
Fixed by setting flag in while check instead of calling continue.
bugprone-throw-keyword-missing ON (but might need to turn off because of MICM error handling)
voidf(int i) {
if (i < 0) {
// Warns exception is created but is not thrown.std::runtime_error("Unexpected argument");
}
}
bugprone-too-small-loop-variable ON
intmain() {
long size = 294967296l;
for (short i = 0; i < size; ++i) {} // warns `i` is too small
}
bugprone-unchecked-optional-access ON
Prevents
voidf(std::optional<int> opt) {
use(*opt); // unsafe: it is unclear whether `opt` has a value.// fixed with if (opt.has_value()) {...}
}
voidf(std::optional<int> opt) {
if (opt.has_value()) {
}
else {
use(opt.value()); // unsafe: it is clear that `opt` does *not* have a value.
}
}
voidf(Foo foo) {
if (foo.opt().has_value()) {
use(*foo.opt()); // unsafe: it is unclear whether `foo.opt()` has a value.// fixed with const auto& foo_opt = foo.opt(); foo_opt.has_value()
}
}
bugprone-undefined-memory-manipulation ON
Finds calls of memory manipulation functions memset(), memcpy() and memmove() on non-TriviallyCopyable objects resulting in undefined behavior.
For example, when using memcpy to copy std::string, pointer data is being copied, and it can result in a double free issue.
structCtor {
Ctor();
Ctor(int);
Ctor(int, int);
Ctor(Ctor *i) {
// All Ctor() calls result in a temporary objectCtor(); // did you intend to call a delegated constructor?Ctor(0); // did you intend to call a delegated constructor?Ctor(1, 2); // did you intend to call a delegated constructor?foo();
}
};
bugprone-unhandled-exception-at-new MAYBE
Finds calls to new with missing exception handler for std::bad_alloc.
Adds significant amount of error handling that for non-mission critical systems may add unnecessary verbosity.
int *f() noexcept {
int *p = newint[1000]; // warning: missing exception handler for allocation failure at 'new'// ...return p;
}
->
int *f1() { // not 'noexcept'int *p = newint[1000]; // no warning: exception can be handled outside// of this function// ...return p;
}
int *f2() noexcept {
try {
int *p = newint[1000]; // no warning: exception is handled// ...return p;
} catch (std::bad_alloc &) {
// ...
}
// ...
}
int *f3() noexcept {
int *p = new (std::nothrow) int[1000]; // no warning: "nothrow" is used// ...return p;
}
bugprone-unhandled-self-assignment ON
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.
classT {
int* p;
public:T(const T &rhs) : p(rhs.p ? newint(*rhs.p) : nullptr) {}
~T() { delete p; }
// ...
T& operator=(const T &rhs) { // warns here due to no self checkdelete p;
p = newint(*rhs.p);
return *this;
}
};
->
classT {
int* p;
public:T(const T &rhs) : p(rhs.p ? newint(*rhs.p) : nullptr) {}
~T() { delete p; }
// ...
T& operator=(const T &rhs) {
if(this == &rhs)
return *this;
delete p;
p = newint(*rhs.p);
return *this;
}
};
bugprone-unique-ptr-array-mismatch ON
Finds initializations of C++ unique pointers to non-array type that are initialized with an array.
std::unique_ptr<Foo> x(new Foo[10]); // -> std::unique_ptr<Foo[]> x(new Foo[10]);// ^ warning: unique pointer to non-array is initialized with array
std::unique_ptr<Foo> x1(new Foo), x2(new Foo[10]); // no replacement// ^ warning: unique pointer to non-array is initialized with array
D d;
std::unique_ptr<Foo, D> x3(new Foo[10], d); // no warning (custom deleter used)structS {
std::unique_ptr<Foo> x(new Foo[10]); // no replacement in this case// ^ warning: unique pointer to non-array is initialized with array
};
bugprone-unsafe-functions ON
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 Annex K. “Bounds-checking interfaces” of C11.
#ifndef __STDC_LIB_EXT1__
#error "Annex K is not supported by the current standard library implementation."
#endif
#define__STDC_WANT_LIB_EXT1__1
#include<string.h>// Defines functions from Annex K.
#include<stdio.h>enum { BUFSIZE = 32 };
voidUnsafe(constchar *Msg) {
staticconstchar Prefix[] = "Error: ";
staticconstchar Suffix[] = "\n";
char Buf[BUFSIZE] = {0};
strcpy(Buf, Prefix); // warning: function 'strcpy' is not bounds-checking; 'strcpy_s' should be used instead.strcat(Buf, Msg); // warning: function 'strcat' is not bounds-checking; 'strcat_s' should be used instead.strcat(Buf, Suffix); // warning: function 'strcat' is not bounds-checking; 'strcat_s' should be used instead.if (fputs(buf, stderr) < 0) {
// error handlingreturn;
}
}
voidUsingSafeFunctions(constchar *Msg) {
staticconstchar Prefix[] = "Error: ";
staticconstchar Suffix[] = "\n";
char Buf[BUFSIZE] = {0};
if (strcpy_s(Buf, BUFSIZE, Prefix) != 0) {
// error handlingreturn;
}
if (strcat_s(Buf, BUFSIZE, Msg) != 0) {
// error handlingreturn;
}
if (strcat_s(Buf, BUFSIZE, Suffix) != 0) {
// error handlingreturn;
}
if (fputs(Buf, stderr) < 0) {
// error handlingreturn;
}
}
bugprone-unused-local-non-trivial-variable ON
Warns when a local non trivial variable is unused within a function.
std::mutex my_lock;
// my_lock local variable is never used
std::future<MyObject> future1;
std::future<MyObject> future2;
// ...
MyObject foo = future1.get();
// future2 is not used.
The destructor of the scoped_lock is called before the critical_section is entered, leaving it unprotected.
bugprone-unused-return-value ON
Warns on unused function return values. The checked functions can be configured.
bugprone-virtual-near-miss ON
Warn if a function is a near miss (i.e. the name is very similar and the function signature is the same) to a virtual function from a base class.
structBase {
virtualvoidfunc();
};
structDerived : Base {
virtualvoidfunk();
// warning: 'Derived::funk' has a similar name and the same signature as virtual method 'Base::func'; did you mean to override it?
};
The text was updated successfully, but these errors were encountered:
Is your feature request related to a problem? Please describe.
No
Describe the solution you'd like
A clang-tidy config file addition that enables the
bugprone-*
checks that are relevant to MICM development.Describe alternatives you've considered
N\A
Additional context
.clang-tidy
modificationsTo Review
clang-tidy
Recommended Checks Reasoningbugprone-argument-comment
ONWe can turn this on but I don't think any modern style uses
functionCall(/*value=*/5)
wherevoid
functionCall(int value)`.bugprone-assert-side-effect
ONRecommend turning on as it will flag things like
assert(++i = 5)
or similarasserts
where there are state modifications that would only be tracked in debug builds.bugprone-assignment-in-if-condition
ONDetects things like
if(i = 5)
when meant to useif(i == 5)
.bugprone-bad-signal-to-kill-thread
ONPrevents using
pthread_kill(thread, SIGTERM);
as this will stop the entire process, not just the thread.bugprone-bool-pointer-implicit-conversion
ON unless needed otherwiseI think leaving this on is a good idea as
int *p = ...; if(p) {...}
is more of a C-style approach.bugprone-branch-clone
ONPrevents
Would flag
x+=1
and anything else in both branches as repeated and can be manually moved out, reducing code.bugprone-casting-through-void
ONDetects unsafe or redundant two-step casting operations involving
void*
bugprone-chained-comparison
ONPrevents
if(a < b < c)
which really evaluatesif ( (a<b)<c)
when probably wantedif( (a<b) && (b<c))
bugprone-compare-pointer-to-member-virtual-function
ONIn 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.
bugprone-copy-constructor-init
ONFinds copy constructors where the constructor doesn’t call the copy constructor of the base class.
bugprone-crtp-constructor-accessibility
MAYBEDetects error-prone Curiously Recurring Template Pattern usage, when the CRTP can be constructed outside itself and the derived class.
Unsure of this one and additional digging is needed
bugprone-dangling-handle
ONDetect dangling references in value handles like
std::string_view
Ex:
vector<string_view> V; V.push_back(string()); // V[0] is dangling.
bugprone-dynamic-static-initializers
ONMight have
foo
called twice by different threads simultaneously resulting ink
being double initialized.bugprone-easily-swappable-parameters
MAYBEThis one can be tricky to handle in every case. For example:
Could be refactored to use a point struct but this is potentially an externally visible API change that might not be possible.
bugprone-empty-catch
ONPrevents
catch(std::exception &e) {}
.bugprone-exception-escape
ONPrevents
void something() noexcept { somethingThatCouldThrow(); }
bugprone-fold-init-type
ONPrevents
Which mistakenly returns
0
because theoperator+
will truncate each operation toint
.bugprone-forward-declaration-namespace
ONPrevents
bugprone-forwarding-reference-overload
ONThe check looks for perfect forwarding constructors that can hide copy or move constructors. (See Scott Meyers, Effective Modern C++, Item 26)
bugprone-implicit-widening-of-multiplication-result
MAYBEFlags:
as
(unsigned) row * (unsigned) col
could be in the space oflong
instead ofint
. The fix isn't terible but there are possibly other gotchas in the fix process, especially ifrow
andcol
are used in other contexts.bugprone-inaccurate-erase
ONPrevents
which only removes the first element and recommends
bugprone-inc-dec-in-conditions
ONPrevents
bugprone-incorrect-enable-if
ONDetects incorrect usages of
std::enable_if
that don’t name the nested type type.bugprone-incorrect-roundings
ONPrevents:
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.
bugprone-infinite-loop
ONPrevents
bugprone-integer-division
ONPrevents
But does not warn on:
bugprone-lambda-function-name
ONPrevents
as this outputs:
bugprone-macro-parentheses
ONPrevents
bugprone-macro-repeated-side-effects
ONPrevents
bugprone-misplaced-operator-in-strlen-in-alloc
ONPrevents
and recommends
bugprone-misplaced-pointer-arithmetic-in-alloc
ONPrevents
and recommends
bugprone-misplaced-widening-cast
ONFlags:
and recommends:
bugprone-move-forwarding-reference
ONFlags
and recommends:
bar(std::forward<T>(t));
bugprone-multi-level-implicit-pointer-conversion
ONPrevents
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.
bugprone-multiple-new-in-one-expression
ONPrevents:
bugprone-multiple-statement-macro
ONPrevents
bugprone-no-escape
ONPrevents
bugprone-non-zero-enum-to-bool-conversion
ONPrevents
bugprone-not-null-terminated-result
ONFlags
and recommends
Checks usage of
memcpy, memcpy_s, memchr, memmove, memmove_s, strerror_s, strncmp, strxfrm
bugprone-optional-value-conversion
ONbecomes
bugprone-parent-virtual-call
ONbugprone-posix-return
ONFlags
if (posix_fadvise(...) < 0) {
and recommends changing the
<
to either=
for success or>
for failurebugprone-redundant-branch-condition
ONFlags
and
but will fail to detect
bugprone-reserved-identifier
ONChecks for usages of identifiers reserved for use by the implementation.
Prevents
bugprone-return-const-ref-from-parameter
ONDetects 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.
bugprone-shared-ptr-array-mismatch
ONFinds initializations of C++ shared pointers to non-array type that are initialized with an array.
If a shared pointer std::shared_ptr is initialized with a new-expression new T[] the memory is not deallocated correctly.
bugprone-signal-handler
OFFFinds specific constructs in signal handler functions that can cause undefined behavior. The rules for what is allowed differ between C++ language versions.
C++17 loosense restrictions thus this is harder to track and not effective (meaning the fix will still be problematic)
Flags
and expects
bugprone-signed-char-misuse
ONCurrently, this check warns in the following cases: - signed char is assigned to an integer variable - signed char and unsigned char are compared with equality/inequality operator - signed char is converted to an integer in the array subscript
bugprone-sizeof-container
ONThe check finds usages of sizeof on expressions of STL container types. Most likely the user wanted to use .size() instead.
bugprone-sizeof-expression
ONThe check finds usages of sizeof expressions which are most likely errors.
...and many others
bugprone-spuriously-wake-up-functions
ONNot sure we will hit this frequently but it flags:
This noncompliant code example nests the call to wait() inside an if block and consequently fails to check the condition predicate after the notification is received. If the notification was spurious or malicious, the thread would wake up prematurely.
This compliant solution calls the wait() member function from within a while loop to check the condition both before and after the call to wait().
bugprone-standalone-empty
ONbugprone-string-constructor
ONbugprone-string-integer-assignment
ONbugprone-string-literal-with-embedded-nul
ONFlags:
bugprone-stringview-nullptr
ONFlags:
and prefers:
bugprone-suspicious-enum-usage
ONbugprone-suspicious-include
ONFlags:
bugprone-suspicious-memory-comparison
ONBecause std::memcmp() performs a bytewise comparison of the object representations, if the implementation uses a vtable pointer as part of the object representation, it will compare vtable pointers. If the dynamic type of either c1 or c2 is a derived class of type C, the comparison may fail despite the value representation of either object.
In this compliant solution, C defines an equality operator that is used instead of calling std::memcmp(). This solution ensures that only the value representation of the objects is considered when performing the comparison.
bugprone-suspicious-memset-usage
ONThis check finds memset() calls with potential mistakes in their arguments.
bugprone-suspicious-missing-comma
ONString 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.
bugprone-suspicious-realloc-usage
ONThis check finds usages of realloc where the return value is assigned to the same expression as passed to the first argument:
p = realloc(p, size);
The problem with this construct is that if realloc fails it returns a null pointer but does not deallocate the original memory.bugprone-suspicious-semicolon
ONFinds most instances of stray semicolons that unexpectedly alter the meaning of the code. More specifically, it looks for
if
,while
,for
andfor-range
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.bugprone-suspicious-string-compare
ONbugprone-suspicious-stringview-data-usage
ONIdentifies suspicious usages of
std::string_view::data()
that could lead to reading out-of-bounds data due to inadequate or incorrect string null termination.bugprone-swapped-arguments
ON (unless too many false positives)Flags
bugprone-switch-missing-default-case
ONbugprone-terminating-continue
ONFixed by setting flag in
while
check instead of callingcontinue
.bugprone-throw-keyword-missing
ON (but might need to turn off because of MICM error handling)bugprone-too-small-loop-variable
ONbugprone-unchecked-optional-access
ONPrevents
bugprone-undefined-memory-manipulation
ONFinds calls of memory manipulation functions memset(), memcpy() and memmove() on non-TriviallyCopyable objects resulting in undefined behavior.
For example, when using memcpy to copy std::string, pointer data is being copied, and it can result in a double free issue.
bugprone-undelegated-constructor
ONbugprone-unhandled-exception-at-new
MAYBEFinds calls to new with missing exception handler for std::bad_alloc.
Adds significant amount of error handling that for non-mission critical systems may add unnecessary verbosity.
bugprone-unhandled-self-assignment
ONFinds 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.
bugprone-unique-ptr-array-mismatch
ONFinds initializations of C++ unique pointers to non-array type that are initialized with an array.
bugprone-unsafe-functions
ONChecks 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 Annex K. “Bounds-checking interfaces” of C11.
bugprone-unused-local-non-trivial-variable
ONWarns when a local non trivial variable is unused within a function.
bugprone-unused-raii
ONFinds temporaries that look like RAII objects.
The destructor of the scoped_lock is called before the
critical_section
is entered, leaving it unprotected.bugprone-unused-return-value
ONWarns on unused function return values. The checked functions can be configured.
bugprone-virtual-near-miss
ONWarn if a function is a near miss (i.e. the name is very similar and the function signature is the same) to a virtual function from a base class.
The text was updated successfully, but these errors were encountered: