[clang-tools-extra] r255630 - [clang-tidy] Check for suspicious string assignments.

Gabor Horvath via cfe-commits cfe-commits at lists.llvm.org
Tue Dec 15 00:48:00 PST 2015


Author: xazax
Date: Tue Dec 15 02:47:20 2015
New Revision: 255630

URL: http://llvm.org/viewvc/llvm-project?rev=255630&view=rev
Log:
[clang-tidy] Check for suspicious string assignments.

It is possible to assign arbitrary integer types to strings.
Sometimes it is the result of missing to_string call or apostrophes.

Reviewers: alexfh

Differential Revision: http://reviews.llvm.org/D15411

Added:
    clang-tools-extra/trunk/clang-tidy/misc/StringIntegerAssignmentCheck.cpp
    clang-tools-extra/trunk/clang-tidy/misc/StringIntegerAssignmentCheck.h
    clang-tools-extra/trunk/docs/clang-tidy/checks/misc-string-integer-assignment.rst
    clang-tools-extra/trunk/test/clang-tidy/misc-string-integer-assignment.cpp
Modified:
    clang-tools-extra/trunk/clang-tidy/misc/CMakeLists.txt
    clang-tools-extra/trunk/clang-tidy/misc/MiscTidyModule.cpp
    clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst

Modified: clang-tools-extra/trunk/clang-tidy/misc/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/misc/CMakeLists.txt?rev=255630&r1=255629&r2=255630&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/misc/CMakeLists.txt (original)
+++ clang-tools-extra/trunk/clang-tidy/misc/CMakeLists.txt Tue Dec 15 02:47:20 2015
@@ -17,6 +17,7 @@ add_clang_library(clangTidyMiscModule
   NonCopyableObjects.cpp
   SizeofContainerCheck.cpp
   StaticAssertCheck.cpp
+  StringIntegerAssignmentCheck.cpp
   SwappedArgumentsCheck.cpp
   ThrowByValueCatchByReferenceCheck.cpp
   UndelegatedConstructor.cpp

Modified: clang-tools-extra/trunk/clang-tidy/misc/MiscTidyModule.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/misc/MiscTidyModule.cpp?rev=255630&r1=255629&r2=255630&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/misc/MiscTidyModule.cpp (original)
+++ clang-tools-extra/trunk/clang-tidy/misc/MiscTidyModule.cpp Tue Dec 15 02:47:20 2015
@@ -25,6 +25,7 @@
 #include "NonCopyableObjects.h"
 #include "SizeofContainerCheck.h"
 #include "StaticAssertCheck.h"
+#include "StringIntegerAssignmentCheck.h"
 #include "SwappedArgumentsCheck.h"
 #include "ThrowByValueCatchByReferenceCheck.h"
 #include "UndelegatedConstructor.h"
@@ -68,6 +69,8 @@ public:
     CheckFactories.registerCheck<SizeofContainerCheck>("misc-sizeof-container");
     CheckFactories.registerCheck<StaticAssertCheck>(
         "misc-static-assert");
+    CheckFactories.registerCheck<StringIntegerAssignmentCheck>(
+        "misc-string-integer-assignment");
     CheckFactories.registerCheck<SwappedArgumentsCheck>(
         "misc-swapped-arguments");
     CheckFactories.registerCheck<ThrowByValueCatchByReferenceCheck>(

Added: clang-tools-extra/trunk/clang-tidy/misc/StringIntegerAssignmentCheck.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/misc/StringIntegerAssignmentCheck.cpp?rev=255630&view=auto
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/misc/StringIntegerAssignmentCheck.cpp (added)
+++ clang-tools-extra/trunk/clang-tidy/misc/StringIntegerAssignmentCheck.cpp Tue Dec 15 02:47:20 2015
@@ -0,0 +1,85 @@
+//===--- StringIntegerAssignmentCheck.cpp - clang-tidy---------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "StringIntegerAssignmentCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Lex/Lexer.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+
+void StringIntegerAssignmentCheck::registerMatchers(MatchFinder *Finder) {
+  if (!getLangOpts().CPlusPlus)
+    return;
+  Finder->addMatcher(
+      cxxOperatorCallExpr(
+          anyOf(hasOverloadedOperatorName("="),
+                hasOverloadedOperatorName("+=")),
+          callee(cxxMethodDecl(ofClass(classTemplateSpecializationDecl(
+              hasName("::std::basic_string"),
+              hasTemplateArgument(0, refersToType(qualType().bind("type"))))))),
+          hasArgument(1,
+                      ignoringImpCasts(expr(hasType(isInteger()),
+                                            unless(hasType(isAnyCharacter())))
+                                           .bind("expr"))),
+          unless(isInTemplateInstantiation())),
+      this);
+}
+
+void StringIntegerAssignmentCheck::check(
+    const MatchFinder::MatchResult &Result) {
+  const auto *Argument = Result.Nodes.getNodeAs<Expr>("expr");
+  SourceLocation Loc = Argument->getLocStart();
+
+  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 "
+                "appropriate character type; if you want a string "
+                "representation, use the appropriate conversion facility");
+
+  if (Loc.isMacroID())
+    return;
+
+  auto CharType = *Result.Nodes.getNodeAs<QualType>("type");
+  bool IsWideCharType = CharType->isWideCharType();
+  if (!CharType->isCharType() && !IsWideCharType)
+    return;
+  bool IsOneDigit = false;
+  bool IsLiteral = false;
+  if (const auto *Literal = dyn_cast<IntegerLiteral>(Argument)) {
+    IsOneDigit = Literal->getValue().getLimitedValue() < 10;
+    IsLiteral = true;
+  }
+
+  SourceLocation EndLoc = Lexer::getLocForEndOfToken(
+      Argument->getLocEnd(), 0, *Result.SourceManager,
+      Result.Context->getLangOpts());
+  if (IsOneDigit) {
+    Diag << FixItHint::CreateInsertion(Loc, IsWideCharType ? "L'" : "'")
+         << FixItHint::CreateInsertion(EndLoc, "'");
+    return;
+  }
+  if (IsLiteral) {
+    Diag << FixItHint::CreateInsertion(Loc, IsWideCharType ? "L\"" : "\"")
+         << FixItHint::CreateInsertion(EndLoc, "\"");
+    return;
+  }
+
+  if (getLangOpts().CPlusPlus11) {
+    Diag << FixItHint::CreateInsertion(Loc, IsWideCharType ? "std::to_wstring("
+                                                           : "std::to_string(")
+         << FixItHint::CreateInsertion(EndLoc, ")");
+  }
+}
+
+} // namespace tidy
+} // namespace clang

Added: clang-tools-extra/trunk/clang-tidy/misc/StringIntegerAssignmentCheck.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/misc/StringIntegerAssignmentCheck.h?rev=255630&view=auto
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/misc/StringIntegerAssignmentCheck.h (added)
+++ clang-tools-extra/trunk/clang-tidy/misc/StringIntegerAssignmentCheck.h Tue Dec 15 02:47:20 2015
@@ -0,0 +1,34 @@
+//===--- StringIntegerAssignmentCheck.h - clang-tidy-------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_STRING_INTEGER_ASSIGNMENT_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_STRING_INTEGER_ASSIGNMENT_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+
+/// Finds instances where an integer is assigned to a string.
+///
+/// For more details see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/misc-string-assignment.html
+class StringIntegerAssignmentCheck : public ClangTidyCheck {
+public:
+  StringIntegerAssignmentCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_STRING_INTEGER_ASSIGNMENT_H
+

Modified: clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst?rev=255630&r1=255629&r2=255630&view=diff
==============================================================================
--- clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst (original)
+++ clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst Tue Dec 15 02:47:20 2015
@@ -48,6 +48,7 @@ List of clang-tidy Checks
    misc-non-copyable-objects
    misc-sizeof-container
    misc-static-assert
+   misc-string-integer-assignment
    misc-swapped-arguments
    misc-throw-by-value-catch-by-reference
    misc-undelegated-constructor

Added: clang-tools-extra/trunk/docs/clang-tidy/checks/misc-string-integer-assignment.rst
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/docs/clang-tidy/checks/misc-string-integer-assignment.rst?rev=255630&view=auto
==============================================================================
--- clang-tools-extra/trunk/docs/clang-tidy/checks/misc-string-integer-assignment.rst (added)
+++ clang-tools-extra/trunk/docs/clang-tidy/checks/misc-string-integer-assignment.rst Tue Dec 15 02:47:20 2015
@@ -0,0 +1,31 @@
+misc-string-integer-assignment
+==============================
+
+The check finds assignments of an integer to ``std::basic_string<CharT>``
+(``std::string``, ``std::wstring``, etc.). The source of the problem is the
+following assignment operator of ``std::basic_string<CharT>``:
+
+.. code:: c++
+  basic_string& operator=( CharT ch );
+
+Numeric types can be implicity casted to character types.
+
+.. code:: c++
+  std::string s;
+  int x = 5965;
+  s = 6;
+  s = x;
+
+Use the appropriate conversion functions or character literals.
+
+.. code:: c++
+  std::string s;
+  int x = 5965;
+  s = '6';
+  s = std::to_string(x);
+
+In order to suppress false positives, use an explicit cast.
+
+.. code:: c++
+  std::string s;
+  s = static_cast<char>(6);

Added: clang-tools-extra/trunk/test/clang-tidy/misc-string-integer-assignment.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clang-tidy/misc-string-integer-assignment.cpp?rev=255630&view=auto
==============================================================================
--- clang-tools-extra/trunk/test/clang-tidy/misc-string-integer-assignment.cpp (added)
+++ clang-tools-extra/trunk/test/clang-tidy/misc-string-integer-assignment.cpp Tue Dec 15 02:47:20 2015
@@ -0,0 +1,53 @@
+// RUN: %check_clang_tidy %s misc-string-integer-assignment %t
+
+namespace std {
+template<typename T>
+struct basic_string {
+  basic_string& operator=(T);
+  basic_string& operator=(basic_string);
+  basic_string& operator+=(T);
+  basic_string& operator+=(basic_string);
+};
+
+typedef basic_string<char> string;
+typedef basic_string<wchar_t> wstring;
+}
+
+typedef int MyArcaneChar;
+
+int main() {
+  std::string s;
+  std::wstring ws;
+  int x = 5;
+
+  s = 6;
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: an integer is interpreted as a character code when assigning {{.*}} [misc-string-integer-assignment]
+// CHECK-FIXES: {{^}}  s = '6';{{$}}
+  s = 66;
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: an integer is interpreted as a chara
+// CHECK-FIXES: {{^}}  s = "66";{{$}}
+  s = x;
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: an integer is interpreted as a chara
+// CHECK-FIXES: {{^}}  s = std::to_string(x);{{$}}
+  s = 'c';
+  s = static_cast<char>(6);
+
+// +=
+  ws += 6;
+// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: an integer is interpreted as a chara
+// CHECK-FIXES: {{^}}  ws += L'6';{{$}}
+  ws += 66;
+// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: an integer is interpreted as a chara
+// CHECK-FIXES: {{^}}  ws += L"66";{{$}}
+  ws += x;
+// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: an integer is interpreted as a chara
+// CHECK-FIXES: {{^}}  ws += std::to_wstring(x);{{$}}
+  ws += L'c';
+  ws += (wchar_t)6;
+
+  std::basic_string<MyArcaneChar> as;
+  as = 6;
+// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: an integer is interpreted as a chara
+// CHECK-FIXES: {{^}}  as = 6;{{$}}
+
+}




More information about the cfe-commits mailing list