Index: clang-tidy/bugprone/SizeofExpressionCheck.cpp =================================================================== --- clang-tidy/bugprone/SizeofExpressionCheck.cpp +++ clang-tidy/bugprone/SizeofExpressionCheck.cpp @@ -84,8 +84,11 @@ 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 @@ 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 @@ } else if (const auto *E = Result.Nodes.getNodeAs("sizeof-multiply-sizeof")) { diag(E->getBeginLoc(), "suspicious 'sizeof' by 'sizeof' multiplication"); + } else if (const auto *E = + Result.Nodes.getNodeAs("sizeof-in-ptr-arithmetic-mul")) { + const auto *LPtrTy = Result.Nodes.getNodeAs("left-ptr-type"); + const auto *RPtrTy = Result.Nodes.getNodeAs("right-ptr-type"); + const auto *SizeofArgTy = Result.Nodes.getNodeAs("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("sizeof-in-ptr-arithmetic-div")) { + const auto *LPtrTy = Result.Nodes.getNodeAs("left-ptr-type"); + const auto *RPtrTy = Result.Nodes.getNodeAs("right-ptr-type"); + const auto *SizeofArgTy = Result.Nodes.getNodeAs("sizeof-arg-type"); + + if ((LPtrTy == RPtrTy) && (LPtrTy == SizeofArgTy)) { + diag(E->getBeginLoc(), "suspicious usage of 'sizeof(...)' in " + "pointer arithmetic"); + } } } Index: test/clang-tidy/bugprone-sizeof-expression.cpp =================================================================== --- test/clang-tidy/bugprone-sizeof-expression.cpp +++ test/clang-tidy/bugprone-sizeof-expression.cpp @@ -231,6 +231,35 @@ 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";