xazax.hun created this revision.
xazax.hun added a reviewer: alexfh.
xazax.hun added subscribers: dkrupp, cfe-commits.

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

This check aims to find such errors.

http://reviews.llvm.org/D15411

Files:
  clang-tidy/misc/CMakeLists.txt
  clang-tidy/misc/MiscTidyModule.cpp
  clang-tidy/misc/StringAssignmentCheck.cpp
  clang-tidy/misc/StringAssignmentCheck.h
  docs/clang-tidy/checks/list.rst
  docs/clang-tidy/checks/misc-string-assignment.rst
  test/clang-tidy/misc-string-assignment.cpp

Index: test/clang-tidy/misc-string-assignment.cpp
===================================================================
--- /dev/null
+++ test/clang-tidy/misc-string-assignment.cpp
@@ -0,0 +1,39 @@
+// RUN: %check_clang_tidy %s misc-string-assignment %t
+
+namespace std {
+template<typename T>
+struct basic_string {
+  basic_string(const T*) {}
+  basic_string& operator=(T) {
+    return *this;
+  }
+  basic_string& operator=(basic_string) {
+    return *this;
+  }
+  basic_string& operator+=(T) {
+    return *this;
+  }
+  basic_string& operator+=(basic_string) {
+    return *this;
+  }
+};
+
+typedef basic_string<char> string;
+}
+
+int main() {
+  std::string s("foobar");
+
+  s = 6;
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: probably missing to_string operation [misc-string-assignment]
+// CHECK-FIXES: {{^}}  s = std::to_string(6);{{$}}
+  s = 'c';
+  s = (char)6;
+
+// +=
+  s += 6;
+// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: probably missing to_string operation [misc-string-assignment]
+// CHECK-FIXES: {{^}}  s += std::to_string(6);{{$}}
+  s += 'c';
+  s += (char)6;
+}
Index: docs/clang-tidy/checks/misc-string-assignment.rst
===================================================================
--- /dev/null
+++ docs/clang-tidy/checks/misc-string-assignment.rst
@@ -0,0 +1,24 @@
+misc-string-assignment
+======================
+
+The ``std::basic_string`` has an assignment operator with the following signature:
+
+.. code:: c++
+  basic_string& operator=( CharT ch );
+
+The source of the problem is that, the numeric types can be implicity casted to most of the
+character types. It possible to assign integers to ``basic_string``.
+
+.. 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);
Index: docs/clang-tidy/checks/list.rst
===================================================================
--- docs/clang-tidy/checks/list.rst
+++ docs/clang-tidy/checks/list.rst
@@ -47,6 +47,7 @@
    misc-non-copyable-objects
    misc-sizeof-container
    misc-static-assert
+   misc-string-assignment
    misc-swapped-arguments
    misc-throw-by-value-catch-by-reference
    misc-undelegated-constructor
Index: clang-tidy/misc/StringAssignmentCheck.h
===================================================================
--- /dev/null
+++ clang-tidy/misc/StringAssignmentCheck.h
@@ -0,0 +1,34 @@
+//===--- StringAssignmentCheck.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_ASSIGNMENT_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_STRING_ASSIGNMENT_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+
+/// Finds instances where integer is assigned to a string.
+///
+/// For more details see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/misc-string-assignment.html
+class StringAssignmentCheck : public ClangTidyCheck {
+public:
+  StringAssignmentCheck(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_ASSIGNMENT_H
+
Index: clang-tidy/misc/StringAssignmentCheck.cpp
===================================================================
--- /dev/null
+++ clang-tidy/misc/StringAssignmentCheck.cpp
@@ -0,0 +1,50 @@
+//===--- StringAssignmentCheck.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 "StringAssignmentCheck.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 StringAssignmentCheck::registerMatchers(MatchFinder *Finder) {
+  auto Matcher = cxxOperatorCallExpr(
+      anyOf(hasOverloadedOperatorName("="), hasOverloadedOperatorName("+=")),
+      callee(cxxMethodDecl(ofClass(hasName("::std::basic_string")))),
+      hasArgument(1, ignoringImpCasts(expr().bind("expr"))),
+      unless(isInTemplateInstantiation()));
+  Finder->addMatcher(Matcher, this);
+}
+
+void StringAssignmentCheck::check(const MatchFinder::MatchResult &Result) {
+  auto Argument = Result.Nodes.getNodeAs<Expr>("expr");
+  QualType ArgType = Argument->getType();
+
+  if (!ArgType->isIntegerType() || ArgType->isAnyCharacterType())
+    return;
+  SourceLocation Loc = Argument->getLocStart();
+  SmallVector<FixItHint, 2> Hints;
+  if (!Loc.isMacroID()) {
+    Hints.push_back(FixItHint::CreateInsertion(Loc, "std::to_string("));
+    Hints.push_back(FixItHint::CreateInsertion(
+        Lexer::getLocForEndOfToken(Argument->getLocEnd(), 0,
+                                   *Result.SourceManager,
+                                   Result.Context->getLangOpts()),
+        ")"));
+  }
+
+  diag(Loc, "probably missing to_string operation") << Hints;
+}
+
+} // namespace tidy
+} // namespace clang
Index: clang-tidy/misc/MiscTidyModule.cpp
===================================================================
--- clang-tidy/misc/MiscTidyModule.cpp
+++ clang-tidy/misc/MiscTidyModule.cpp
@@ -25,6 +25,7 @@
 #include "NonCopyableObjects.h"
 #include "SizeofContainerCheck.h"
 #include "StaticAssertCheck.h"
+#include "StringAssignmentCheck.h"
 #include "SwappedArgumentsCheck.h"
 #include "ThrowByValueCatchByReferenceCheck.h"
 #include "UndelegatedConstructor.h"
@@ -68,6 +69,8 @@
     CheckFactories.registerCheck<SizeofContainerCheck>("misc-sizeof-container");
     CheckFactories.registerCheck<StaticAssertCheck>(
         "misc-static-assert");
+    CheckFactories.registerCheck<StringAssignmentCheck>(
+        "misc-string-assignment");
     CheckFactories.registerCheck<SwappedArgumentsCheck>(
         "misc-swapped-arguments");
     CheckFactories.registerCheck<ThrowByValueCatchByReferenceCheck>(
Index: clang-tidy/misc/CMakeLists.txt
===================================================================
--- clang-tidy/misc/CMakeLists.txt
+++ clang-tidy/misc/CMakeLists.txt
@@ -17,6 +17,7 @@
   NonCopyableObjects.cpp
   SizeofContainerCheck.cpp
   StaticAssertCheck.cpp
+  StringAssignmentCheck.cpp
   SwappedArgumentsCheck.cpp
   ThrowByValueCatchByReferenceCheck.cpp
   UndelegatedConstructor.cpp
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to