[clang-tidy][NFC] Add missing Option tests in bugprone [1/N] (#184015)

This PR adds testcases for untested Options in `bugprone` module for
better test coverage, specifically:
- `bugprone-implicit-widening-of-multiplication-result`:
`UseCXXHeadersInCppSources` and `IncludeStyle`.
- `bugprone-not-null-terminated-result`: `WantToUseSafeFunctions`
- `bugprone-signed-char-misuse`: `DiagnoseSignedUnsignedCharComparisons`
- `bugprone-sizeof-expression`: `WarnOnSizeOfConstant`,
`WarnOnSizeOfThis`, `WarnOnSizeOfCompareToConstant`,
`WarnOnSizeOfInLoopTermination`.
- `bugprone-string-constructor`: `WarnOnLargeLength`,
`LargeLengthThreshold`, `StringNames`.
- `bugprone-suspicious-missing-comma`: `SizeThreshold`,
`RatioThreshold`, `MaxConcatenatedTokens`.
- `bugprone-suspicious-string-compare`: `StringCompareLikeFunctions`
- `bugprone-suspicious-stringview-data-usage`: `StringViewTypes`,
`AllowedCallees`

As of AI Usage: Assisted by Gemini 3 and Claude (Writing part of the
testcases and pre-commit reviewing).
This commit is contained in:
mitchell 2026-03-04 18:09:52 +08:00 committed by GitHub
parent 732f66eccc
commit b6761b287f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 266 additions and 0 deletions

View File

@ -0,0 +1,19 @@
// RUN: %check_clang_tidy %s bugprone-implicit-widening-of-multiplication-result %t -- \
// RUN: -config="{CheckOptions: { \
// RUN: bugprone-implicit-widening-of-multiplication-result.UseCXXHeadersInCppSources: false, \
// RUN: bugprone-implicit-widening-of-multiplication-result.IncludeStyle: google \
// RUN: }}" -- -target x86_64-unknown-unknown -x c++
long mul(int a, int b) {
return a * b;
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: performing an implicit widening conversion to type 'long' of a multiplication performed in type 'int' [bugprone-implicit-widening-of-multiplication-result]
// CHECK-MESSAGES: :[[@LINE-2]]:10: note: make conversion explicit to silence this warning
// CHECK-MESSAGES: :[[@LINE-3]]:10: note: perform multiplication in a wider type
}
long ptr_off(int a, int b, char *p) {
return p[a * b];
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: result of multiplication in type 'int' is used as a pointer offset after an implicit widening conversion to type 'ptrdiff_t' [bugprone-implicit-widening-of-multiplication-result]
// CHECK-MESSAGES: :[[@LINE-2]]:12: note: make conversion explicit to silence this warning
// CHECK-MESSAGES: :[[@LINE-3]]:12: note: perform multiplication in a wider type
}

View File

@ -0,0 +1,17 @@
// RUN: %check_clang_tidy %s bugprone-not-null-terminated-result %t -- \
// RUN: -config="{CheckOptions: { \
// RUN: bugprone-not-null-terminated-result.WantToUseSafeFunctions: false \
// RUN: }}" -- -I %S/Inputs/not-null-terminated-result
#include "not-null-terminated-result-c.h"
#define __STDC_LIB_EXT1__ 1
#define __STDC_WANT_LIB_EXT1__ 1
void test_memcpy_no_safe(const char *src) {
char dest[13];
memcpy(dest, src, strlen(src));
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: the result from calling 'memcpy' is not null-terminated [bugprone-not-null-terminated-result]
// CHECK-FIXES: char dest[14];
// CHECK-FIXES-NEXT: strcpy(dest, src);
}

View File

@ -0,0 +1,18 @@
// RUN: %check_clang_tidy %s bugprone-signed-char-misuse %t -- \
// RUN: -config="{CheckOptions: { \
// RUN: bugprone-signed-char-misuse.DiagnoseSignedUnsignedCharComparisons: false \
// RUN: }}"
int SignedToIntConversion() {
signed char CCharacter = -5;
int NCharacter = CCharacter;
// CHECK-MESSAGES: [[@LINE-1]]:20: warning: 'signed char' to 'int' conversion; consider casting to 'unsigned char' first. [bugprone-signed-char-misuse]
return NCharacter;
}
int SignedUnsignedCharComparison(signed char SCharacter) {
unsigned char USCharacter = 'a';
if (SCharacter == USCharacter)
return 1;
return 0;
}

View File

@ -0,0 +1,33 @@
// RUN: %check_clang_tidy %s bugprone-sizeof-expression %t -- \
// RUN: -config="{CheckOptions: { \
// RUN: bugprone-sizeof-expression.WarnOnSizeOfConstant: false, \
// RUN: bugprone-sizeof-expression.WarnOnSizeOfThis: false, \
// RUN: bugprone-sizeof-expression.WarnOnSizeOfCompareToConstant: false, \
// RUN: bugprone-sizeof-expression.WarnOnSizeOfInLoopTermination: false \
// RUN: }}"
#define LEN 8
class C {
int size() { return sizeof(this); }
};
int Test() {
int A = sizeof(LEN);
int B = sizeof(LEN + 1);
int C = sizeof(1);
if (sizeof(A) < 0x100000)
return 0;
if (sizeof(A) <= 0)
return 0;
int arr[10];
for (int i = 0; sizeof(arr) < i; ++i) {}
while (sizeof(arr) < 10) {}
int x = sizeof(A, 1);
// CHECK-MESSAGES: [[@LINE-1]]:19: warning: suspicious usage of 'sizeof(..., ...)' [bugprone-sizeof-expression]
return A + B + C + x;
}

View File

@ -0,0 +1,43 @@
// RUN: %check_clang_tidy %s bugprone-string-constructor %t -- \
// RUN: -config="{CheckOptions: { \
// RUN: bugprone-string-constructor.WarnOnLargeLength: true, \
// RUN: bugprone-string-constructor.LargeLengthThreshold: 10, \
// RUN: bugprone-string-constructor.StringNames: '::std::basic_string;::std::basic_string_view;::custom::String' \
// RUN: }}" -- -isystem %clang_tidy_headers
#include <string>
namespace custom {
struct String {
String(const char *, unsigned int size);
String(const char *);
};
} // namespace custom
extern const char *kPtr;
void TestLargeLengthThreshold() {
std::string s1(kPtr, 11);
// CHECK-MESSAGES: [[@LINE-1]]:15: warning: suspicious large length parameter [bugprone-string-constructor]
std::string s2(kPtr, 9);
std::string_view sv1(kPtr, 11);
// CHECK-MESSAGES: [[@LINE-1]]:20: warning: suspicious large length parameter [bugprone-string-constructor]
std::string s3(kPtr, 0x1000000);
// CHECK-MESSAGES: [[@LINE-1]]:15: warning: suspicious large length parameter [bugprone-string-constructor]
}
void TestWarnOnLargeLengthAndThreshold() {
std::string s1(kPtr, 0x1000000);
// CHECK-MESSAGES: [[@LINE-1]]:15: warning: suspicious large length parameter [bugprone-string-constructor]
std::string s2(20, 'x');
// CHECK-MESSAGES: [[@LINE-1]]:15: warning: suspicious large length parameter [bugprone-string-constructor]
}
void TestStringNames() {
custom::String cs1(nullptr);
// CHECK-MESSAGES: [[@LINE-1]]:18: warning: constructing string from nullptr is undefined behaviour [bugprone-string-constructor]
}

View File

@ -0,0 +1,32 @@
// RUN: %check_clang_tidy -check-suffixes=THRESHOLD %s bugprone-suspicious-missing-comma %t -- \
// RUN: -config="{CheckOptions: { \
// RUN: bugprone-suspicious-missing-comma.SizeThreshold: 3, \
// RUN: bugprone-suspicious-missing-comma.RatioThreshold: '.5', \
// RUN: bugprone-suspicious-missing-comma.MaxConcatenatedTokens: 3 \
// RUN: }}"
const char *SmallArray[] = {
"hello" "world",
"foo",
"bar",
};
// CHECK-MESSAGES-THRESHOLD: :[[@LINE-4]]:5: warning: suspicious string literal, probably missing a comma [bugprone-suspicious-missing-comma]
const char *ManyTokensArray[] = {
"a" "b" "c",
"d",
"e",
};
const char *TwoTokensArray[] = {
"a" "b",
"c",
"d",
};
// CHECK-MESSAGES-THRESHOLD: :[[@LINE-4]]:5: warning: suspicious string literal, probably missing a comma [bugprone-suspicious-missing-comma]
const char *HighRatioArray[] = {
"a" "b",
"c" "d",
"e",
};

View File

@ -0,0 +1,26 @@
// RUN: %check_clang_tidy %s bugprone-suspicious-string-compare %t -- \
// RUN: -config="{CheckOptions: { \
// RUN: bugprone-suspicious-string-compare.StringCompareLikeFunctions: 'my_strcmp;my_strncmp' \
// RUN: }}"
int my_strcmp(const char *, const char *);
int my_strncmp(const char *, const char *, unsigned long);
void TestCustomCompareFunctions() {
if (my_strcmp("a", "b"))
return;
// CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'my_strcmp' is called without explicitly comparing result [bugprone-suspicious-string-compare]
// CHECK-FIXES: if (my_strcmp("a", "b") != 0)
if (my_strncmp("a", "b", 1))
return;
// CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'my_strncmp' is called without explicitly comparing result [bugprone-suspicious-string-compare]
// CHECK-FIXES: if (my_strncmp("a", "b", 1) != 0)
if (my_strcmp("a", "b") == 1)
return;
// CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'my_strcmp' is compared to a suspicious constant [bugprone-suspicious-string-compare]
if (my_strcmp("a", "b") == 0)
return;
}

View File

@ -0,0 +1,42 @@
// RUN: %check_clang_tidy -std=c++17-or-later %s bugprone-suspicious-stringview-data-usage %t -- \
// RUN: -config="{CheckOptions: { \
// RUN: bugprone-suspicious-stringview-data-usage.StringViewTypes: '::custom::StrView', \
// RUN: bugprone-suspicious-stringview-data-usage.AllowedCallees: '::safe_func;SafeClass' \
// RUN: }}" -- -isystem %clang_tidy_headers
#include <string>
namespace custom {
struct StrView {
const char *data();
unsigned size();
};
} // namespace custom
void unsafe_func(const char *);
void safe_func(const char *);
struct SafeClass {
SafeClass(const char *);
};
struct UnsafeClass {
UnsafeClass(const char *);
};
void TestStringViewTypes(custom::StrView sv) {
unsafe_func(sv.data());
// CHECK-MESSAGES: :[[@LINE-1]]:18: warning: result of a `data()` call may not be null terminated, provide size information to the callee to prevent potential issues [bugprone-suspicious-stringview-data-usage]
}
void TestAllowedCallees(custom::StrView sv) {
safe_func(sv.data());
SafeClass sc(sv.data());
// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: result of a `data()` call may not be null terminated, provide size information to the callee to prevent potential issues [bugprone-suspicious-stringview-data-usage]
}
void TestNotAllowed(custom::StrView sv) {
UnsafeClass uc(sv.data());
// CHECK-MESSAGES: :[[@LINE-1]]:21: warning: result of a `data()` call may not be null terminated, provide size information to the callee to prevent potential issues [bugprone-suspicious-stringview-data-usage]
}
void TestStdStringViewNotMatched(std::string_view sv) {
unsafe_func(sv.data());
}

View File

@ -0,0 +1,36 @@
// RUN: %check_clang_tidy %s bugprone-unused-return-value %t -- \
// RUN: -config="{CheckOptions: { \
// RUN: bugprone-unused-return-value.CheckedReturnTypes: '::CustomError;::ns::Result', \
// RUN: bugprone-unused-return-value.CheckedFunctions: '' \
// RUN: }}"
struct CustomError {
int code;
};
namespace ns {
struct Result {
bool ok;
};
} // namespace ns
struct NotChecked {
int value;
};
CustomError makeError();
ns::Result doWork();
NotChecked other();
void TestCheckedReturnTypes() {
makeError();
// CHECK-MESSAGES: [[@LINE-1]]:3: warning: the value returned by this function should not be disregarded; neglecting it may lead to errors [bugprone-unused-return-value]
doWork();
// CHECK-MESSAGES: [[@LINE-1]]:3: warning: the value returned by this function should not be disregarded; neglecting it may lead to errors [bugprone-unused-return-value]
other();
CustomError e = makeError();
ns::Result r = doWork();
}