summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang-tools-extra/clang-tidy/bugprone/SizeofExpressionCheck.cpp57
-rw-r--r--clang-tools-extra/test/clang-tidy/bugprone-sizeof-expression.cpp29
2 files changed, 84 insertions, 2 deletions
diff --git a/clang-tools-extra/clang-tidy/bugprone/SizeofExpressionCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/SizeofExpressionCheck.cpp
index 959e0ae39b3..fb161957c5a 100644
--- a/clang-tools-extra/clang-tidy/bugprone/SizeofExpressionCheck.cpp
+++ b/clang-tools-extra/clang-tidy/bugprone/SizeofExpressionCheck.cpp
@@ -84,8 +84,11 @@ void SizeofExpressionCheck::registerMatchers(MatchFinder *Finder) {
const auto IntegerCallExpr = expr(ignoringParenImpCasts(
callExpr(anyOf(hasType(isInteger()), hasType(enumType())),
unless(isInTemplateInstantiation()))));
- const auto SizeOfExpr =
- expr(anyOf(sizeOfExpr(has(type())), sizeOfExpr(has(expr()))));
+ const auto SizeOfExpr = expr(anyOf(
+ sizeOfExpr(
+ has(hasUnqualifiedDesugaredType(type().bind("sizeof-arg-type")))),
+ sizeOfExpr(has(expr(hasType(
+ hasUnqualifiedDesugaredType(type().bind("sizeof-arg-type"))))))));
const auto SizeOfZero = expr(
sizeOfExpr(has(ignoringParenImpCasts(expr(integerLiteral(equals(0)))))));
@@ -209,6 +212,36 @@ void SizeofExpressionCheck::registerMatchers(MatchFinder *Finder) {
hasSizeOfDescendant(8, expr(SizeOfExpr, unless(SizeOfZero))))))))
.bind("sizeof-sizeof-expr"),
this);
+
+ // Detect sizeof in pointer aritmetic like: N * sizeof(S) == P1 - P2 or
+ // (P1 - P2) / sizeof(S) where P1 and P2 are pointers to type S.
+ const auto PtrDiffExpr = binaryOperator(
+ hasOperatorName("-"),
+ hasLHS(expr(hasType(hasUnqualifiedDesugaredType(pointerType(pointee(
+ hasUnqualifiedDesugaredType(type().bind("left-ptr-type")))))))),
+ hasRHS(expr(hasType(hasUnqualifiedDesugaredType(pointerType(pointee(
+ hasUnqualifiedDesugaredType(type().bind("right-ptr-type")))))))));
+
+ Finder->addMatcher(
+ binaryOperator(
+ anyOf(hasOperatorName("=="), hasOperatorName("!="),
+ hasOperatorName("<"), hasOperatorName("<="),
+ hasOperatorName(">"), hasOperatorName(">="),
+ hasOperatorName("+"), hasOperatorName("-")),
+ hasEitherOperand(expr(anyOf(
+ ignoringParenImpCasts(SizeOfExpr),
+ ignoringParenImpCasts(binaryOperator(
+ hasOperatorName("*"),
+ hasEitherOperand(ignoringParenImpCasts(SizeOfExpr))))))),
+ hasEitherOperand(ignoringParenImpCasts(PtrDiffExpr)))
+ .bind("sizeof-in-ptr-arithmetic-mul"),
+ this);
+
+ Finder->addMatcher(binaryOperator(hasOperatorName("/"),
+ hasLHS(ignoringParenImpCasts(PtrDiffExpr)),
+ hasRHS(ignoringParenImpCasts(SizeOfExpr)))
+ .bind("sizeof-in-ptr-arithmetic-div"),
+ this);
}
void SizeofExpressionCheck::check(const MatchFinder::MatchResult &Result) {
@@ -275,6 +308,26 @@ void SizeofExpressionCheck::check(const MatchFinder::MatchResult &Result) {
} else if (const auto *E =
Result.Nodes.getNodeAs<Expr>("sizeof-multiply-sizeof")) {
diag(E->getBeginLoc(), "suspicious 'sizeof' by 'sizeof' multiplication");
+ } else if (const auto *E =
+ Result.Nodes.getNodeAs<Expr>("sizeof-in-ptr-arithmetic-mul")) {
+ const auto *LPtrTy = Result.Nodes.getNodeAs<Type>("left-ptr-type");
+ const auto *RPtrTy = Result.Nodes.getNodeAs<Type>("right-ptr-type");
+ const auto *SizeofArgTy = Result.Nodes.getNodeAs<Type>("sizeof-arg-type");
+
+ if ((LPtrTy == RPtrTy) && (LPtrTy == SizeofArgTy)) {
+ diag(E->getBeginLoc(), "suspicious usage of 'sizeof(...)' in "
+ "pointer arithmetic");
+ }
+ } else if (const auto *E =
+ Result.Nodes.getNodeAs<Expr>("sizeof-in-ptr-arithmetic-div")) {
+ const auto *LPtrTy = Result.Nodes.getNodeAs<Type>("left-ptr-type");
+ const auto *RPtrTy = Result.Nodes.getNodeAs<Type>("right-ptr-type");
+ const auto *SizeofArgTy = Result.Nodes.getNodeAs<Type>("sizeof-arg-type");
+
+ if ((LPtrTy == RPtrTy) && (LPtrTy == SizeofArgTy)) {
+ diag(E->getBeginLoc(), "suspicious usage of 'sizeof(...)' in "
+ "pointer arithmetic");
+ }
}
}
diff --git a/clang-tools-extra/test/clang-tidy/bugprone-sizeof-expression.cpp b/clang-tools-extra/test/clang-tidy/bugprone-sizeof-expression.cpp
index 683ad083007..57b73ea4dc9 100644
--- a/clang-tools-extra/test/clang-tidy/bugprone-sizeof-expression.cpp
+++ b/clang-tools-extra/test/clang-tidy/bugprone-sizeof-expression.cpp
@@ -231,6 +231,35 @@ int Test5() {
return sum;
}
+int Test6() {
+ int sum = 0;
+
+ struct S A = AsStruct(), B = AsStruct();
+ struct S *P = &A, *Q = &B;
+ sum += sizeof(struct S) == P - Q;
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(...)' in pointer arithmetic
+ sum += 5 * sizeof(S) != P - Q;
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(...)' in pointer arithmetic
+ sum += sizeof(S) < P - Q;
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(...)' in pointer arithmetic
+ sum += 5 * sizeof(S) <= P - Q;
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(...)' in pointer arithmetic
+ sum += 5 * sizeof(*P) >= P - Q;
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(...)' in pointer arithmetic
+ sum += Q - P > 3 * sizeof(*P);
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(...)' in pointer arithmetic
+ sum += sizeof(S) + (P - Q);
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(...)' in pointer arithmetic
+ sum += 5 * sizeof(S) - (P - Q);
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(...)' in pointer arithmetic
+ sum += (P - Q) / sizeof(S);
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(...)' in pointer arithmetic
+ sum += (P - Q) / sizeof(*Q);
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(...)' in pointer arithmetic
+
+ return sum;
+}
+
int ValidExpressions() {
int A[] = {1, 2, 3, 4};
static const char str[] = "hello";
OpenPOWER on IntegriCloud