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;{{$}} + +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits