[clang-tools-extra] [WIP] Warn about misuse of sizeof operator in loops. (PR #143205)
Malavika Samak via cfe-commits
cfe-commits at lists.llvm.org
Fri Jun 6 14:01:20 PDT 2025
https://github.com/malavikasamak created https://github.com/llvm/llvm-project/pull/143205
None
>From 52e4413ea1e701dfe0b24cf957a26bb72732f066 Mon Sep 17 00:00:00 2001
From: MalavikaSamak <malavika2 at apple.com>
Date: Wed, 21 May 2025 16:06:44 -0700
Subject: [PATCH] Place holder message for sizeof operator in loops.
---
.../bugprone/SizeofExpressionCheck.cpp | 17 +++++++++-
.../bugprone/SizeofExpressionCheck.h | 1 +
.../checkers/bugprone/sizeof-expression.cpp | 31 +++++++++++++++++++
3 files changed, 48 insertions(+), 1 deletion(-)
diff --git a/clang-tools-extra/clang-tidy/bugprone/SizeofExpressionCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/SizeofExpressionCheck.cpp
index f3d4c2255d86e..ee66a880792b8 100644
--- a/clang-tools-extra/clang-tidy/bugprone/SizeofExpressionCheck.cpp
+++ b/clang-tools-extra/clang-tidy/bugprone/SizeofExpressionCheck.cpp
@@ -72,7 +72,8 @@ SizeofExpressionCheck::SizeofExpressionCheck(StringRef Name,
Options.get("WarnOnSizeOfPointerToAggregate", true)),
WarnOnSizeOfPointer(Options.get("WarnOnSizeOfPointer", false)),
WarnOnOffsetDividedBySizeOf(
- Options.get("WarnOnOffsetDividedBySizeOf", true)) {}
+ Options.get("WarnOnOffsetDividedBySizeOf", true)),
+ WarnOnLoopExprSizeOf(Options.get("WarnOnLoopExprSizeOf", true)) {}
void SizeofExpressionCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
Options.store(Opts, "WarnOnSizeOfConstant", WarnOnSizeOfConstant);
@@ -86,6 +87,7 @@ void SizeofExpressionCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
Options.store(Opts, "WarnOnSizeOfPointer", WarnOnSizeOfPointer);
Options.store(Opts, "WarnOnOffsetDividedBySizeOf",
WarnOnOffsetDividedBySizeOf);
+ Options.store(Opts, "WarnOnLoopExprSizeOf", WarnOnLoopExprSizeOf);
}
void SizeofExpressionCheck::registerMatchers(MatchFinder *Finder) {
@@ -93,6 +95,11 @@ void SizeofExpressionCheck::registerMatchers(MatchFinder *Finder) {
// Some of the checks should not match in template code to avoid false
// positives if sizeof is applied on template argument.
+ auto LoopExpr =
+ [](const ast_matchers::internal::Matcher<Stmt> &InnerMatcher) {
+ return stmt(anyOf(forStmt(InnerMatcher), whileStmt(InnerMatcher)));
+ };
+
const auto IntegerExpr = ignoringParenImpCasts(integerLiteral());
const auto ConstantExpr = ignoringParenImpCasts(
anyOf(integerLiteral(), unaryOperator(hasUnaryOperand(IntegerExpr)),
@@ -130,6 +137,11 @@ void SizeofExpressionCheck::registerMatchers(MatchFinder *Finder) {
this);
}
+ if (WarnOnLoopExprSizeOf) {
+ Finder->addMatcher(
+ LoopExpr(has(binaryOperator(has(SizeOfExpr)))).bind("loop-expr"), this);
+ }
+
// Detect sizeof(kPtr) where kPtr is 'const char* kPtr = "abc"';
const auto CharPtrType = pointerType(pointee(isAnyCharacter()));
const auto ConstStrLiteralDecl =
@@ -353,6 +365,9 @@ void SizeofExpressionCheck::check(const MatchFinder::MatchResult &Result) {
diag(E->getBeginLoc(),
"suspicious usage of 'sizeof(char*)'; do you mean 'strlen'?")
<< E->getSourceRange();
+ } else if (const auto *E = Result.Nodes.getNodeAs<Stmt>("loop-expr")) {
+ diag(E->getBeginLoc(), "suspicious usage of 'sizeof' in the loop")
+ << E->getSourceRange();
} else if (const auto *E = Result.Nodes.getNodeAs<Expr>("sizeof-pointer")) {
if (Result.Nodes.getNodeAs<Type>("struct-type")) {
diag(E->getBeginLoc(),
diff --git a/clang-tools-extra/clang-tidy/bugprone/SizeofExpressionCheck.h b/clang-tools-extra/clang-tidy/bugprone/SizeofExpressionCheck.h
index fbd62cb80fb2d..f7dccf39687a5 100644
--- a/clang-tools-extra/clang-tidy/bugprone/SizeofExpressionCheck.h
+++ b/clang-tools-extra/clang-tidy/bugprone/SizeofExpressionCheck.h
@@ -32,6 +32,7 @@ class SizeofExpressionCheck : public ClangTidyCheck {
const bool WarnOnSizeOfPointerToAggregate;
const bool WarnOnSizeOfPointer;
const bool WarnOnOffsetDividedBySizeOf;
+ const bool WarnOnLoopExprSizeOf;
};
} // namespace clang::tidy::bugprone
diff --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone/sizeof-expression.cpp b/clang-tools-extra/test/clang-tidy/checkers/bugprone/sizeof-expression.cpp
index 5e6f394152e9d..52b71277466b1 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/bugprone/sizeof-expression.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/sizeof-expression.cpp
@@ -164,6 +164,37 @@ int Test2(MyConstChar* A) {
return sum;
}
+struct A {
+ int array[10];
+};
+
+struct B {
+ struct A a;
+};
+
+int square(int num, struct B b) {
+ struct A arr[10];
+ // CHECK-MESSAGES: :[[@LINE+1]]:5: warning: suspicious usage of 'sizeof' in the loop [bugprone-sizeof-expression]
+ for(int i = 0; i < sizeof(arr); i++) {
+ struct A a = arr[i];
+ }
+ // CHECK-MESSAGES: :[[@LINE+2]]:24: warning: suspicious usage of 'sizeof(K)'; did you mean 'K'? [bugprone-sizeof-expression]
+ // CHECK-MESSAGES: :[[@LINE+1]]:34: warning: suspicious usage of 'sizeof(...)/sizeof(...)'; numerator is not a multiple of denominator [bugprone-sizeof-expression]
+ for(int i = 0; i < sizeof(10)/sizeof(A); i++) {
+ struct A a = arr[i];
+ }
+
+ for(int i = 0; i < sizeof(arr)/sizeof(A); i++) {
+ struct A a = arr[i];
+ }
+
+ // CHECK-MESSAGES: :[[@LINE+1]]:5: warning: suspicious usage of 'sizeof' in the loop [bugprone-sizeof-expression]
+ for(int j = 0; j < sizeof(b.a); j++) {
+
+ }
+ return 2;
+}
+
template <int T>
int Foo() { int A[T]; return sizeof(T); }
// CHECK-MESSAGES: :[[@LINE-1]]:30: warning: suspicious usage of 'sizeof(K)'
More information about the cfe-commits
mailing list