[PATCH] D58609: [clang-tidy] bugprone-string-integer-assignment: Reduce false positives.

Clement Courbet via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Thu Feb 28 02:35:04 PST 2019


courbet updated this revision to Diff 188690.
courbet marked an inline comment as done.
courbet added a comment.

- rebase
- -more cosmetics


Repository:
  rCTE Clang Tools Extra

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D58609/new/

https://reviews.llvm.org/D58609

Files:
  clang-tidy/bugprone/StringIntegerAssignmentCheck.cpp
  test/clang-tidy/bugprone-string-integer-assignment.cpp


Index: test/clang-tidy/bugprone-string-integer-assignment.cpp
===================================================================
--- test/clang-tidy/bugprone-string-integer-assignment.cpp
+++ test/clang-tidy/bugprone-string-integer-assignment.cpp
@@ -59,4 +59,11 @@
   s += toupper(x);
   s += tolower(x);
   s += std::tolower(x);
+
+  // Likely character expressions.
+  s += x & 0xff;
+  s += 0xff & x;
+
+  s += 'a' + (x % 26);
+  s += (x % 10) + 'b';
 }
Index: clang-tidy/bugprone/StringIntegerAssignmentCheck.cpp
===================================================================
--- clang-tidy/bugprone/StringIntegerAssignmentCheck.cpp
+++ clang-tidy/bugprone/StringIntegerAssignmentCheck.cpp
@@ -45,11 +45,40 @@
       this);
 }
 
+static bool isLikelyCharExpression(const Expr *Argument,
+                                   const ASTContext &Ctx) {
+  const auto *BinOp = dyn_cast<BinaryOperator>(Argument);
+  if (!BinOp)
+    return false;
+  const auto *LHS = BinOp->getLHS()->IgnoreParenImpCasts();
+  const auto *RHS = BinOp->getRHS()->IgnoreParenImpCasts();
+  // <expr> & <mask>, mask is a compile time constant.
+  Expr::EvalResult RHSVal;
+  if (BinOp->getOpcode() == BO_And &&
+      (RHS->EvaluateAsInt(RHSVal, Ctx, Expr::SE_AllowSideEffects) ||
+       LHS->EvaluateAsInt(RHSVal, Ctx, Expr::SE_AllowSideEffects)))
+    return true;
+  // <char literal> + (<expr> % <mod>), where <base> is a char literal.
+  const auto IsCharPlusModExpr = [](const Expr *L, const Expr *R) {
+    const auto *ROp = dyn_cast<BinaryOperator>(R);
+    return ROp && ROp->getOpcode() == BO_Rem && isa<CharacterLiteral>(L);
+  };
+  if (BinOp->getOpcode() == BO_Add) {
+    if (IsCharPlusModExpr(LHS, RHS) || IsCharPlusModExpr(RHS, LHS))
+      return true;
+  }
+  return false;
+}
+
 void StringIntegerAssignmentCheck::check(
     const MatchFinder::MatchResult &Result) {
   const auto *Argument = Result.Nodes.getNodeAs<Expr>("expr");
   SourceLocation Loc = Argument->getBeginLoc();
 
+  // Try to detect a few common expressions to reduce false positives.
+  if (isLikelyCharExpression(Argument, *Result.Context))
+    return;
+
   auto Diag =
       diag(Loc, "an integer is interpreted as a character code when assigning "
                 "it to a string; if this is intended, cast the integer to the "


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D58609.188690.patch
Type: text/x-patch
Size: 2311 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20190228/5a8b8888/attachment.bin>


More information about the cfe-commits mailing list