clang-tools 6.0.0

StringIntegerAssignmentCheck.cpp
Go to the documentation of this file.
1 //===--- StringIntegerAssignmentCheck.cpp - clang-tidy---------------------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #include "StringIntegerAssignmentCheck.h"
11 #include "clang/AST/ASTContext.h"
12 #include "clang/ASTMatchers/ASTMatchFinder.h"
13 #include "clang/Lex/Lexer.h"
14
15 using namespace clang::ast_matchers;
16
17 namespace clang {
18 namespace tidy {
19 namespace misc {
20
21 void StringIntegerAssignmentCheck::registerMatchers(MatchFinder *Finder) {
22 if (!getLangOpts().CPlusPlus)
23 return;
24 Finder->addMatcher(
25 cxxOperatorCallExpr(
26 anyOf(hasOverloadedOperatorName("="),
27 hasOverloadedOperatorName("+=")),
28 callee(cxxMethodDecl(ofClass(classTemplateSpecializationDecl(
29 hasName("::std::basic_string"),
30 hasTemplateArgument(0, refersToType(qualType().bind("type"))))))),
31 hasArgument(1,
32 ignoringImpCasts(expr(hasType(isInteger()),
33 unless(hasType(isAnyCharacter())))
34 .bind("expr"))),
35 unless(isInTemplateInstantiation())),
36 this);
37 }
38
39 void StringIntegerAssignmentCheck::check(
40 const MatchFinder::MatchResult &Result) {
41 const auto *Argument = Result.Nodes.getNodeAs<Expr>("expr");
42 SourceLocation Loc = Argument->getLocStart();
43
44 auto Diag =
45 diag(Loc, "an integer is interpreted as a character code when assigning "
46 "it to a string; if this is intended, cast the integer to the "
47 "appropriate character type; if you want a string "
48 "representation, use the appropriate conversion facility");
49
50 if (Loc.isMacroID())
51 return;
52
53 auto CharType = *Result.Nodes.getNodeAs<QualType>("type");
54 bool IsWideCharType = CharType->isWideCharType();
55 if (!CharType->isCharType() && !IsWideCharType)
56 return;
57 bool IsOneDigit = false;
58 bool IsLiteral = false;
59 if (const auto *Literal = dyn_cast<IntegerLiteral>(Argument)) {
60 IsOneDigit = Literal->getValue().getLimitedValue() < 10;
61 IsLiteral = true;
62 }
63
64 SourceLocation EndLoc = Lexer::getLocForEndOfToken(
65 Argument->getLocEnd(), 0, *Result.SourceManager, getLangOpts());
66 if (IsOneDigit) {
67 Diag << FixItHint::CreateInsertion(Loc, IsWideCharType ? "L'" : "'")
68 << FixItHint::CreateInsertion(EndLoc, "'");
69 return;
70 }
71 if (IsLiteral) {
72 Diag << FixItHint::CreateInsertion(Loc, IsWideCharType ? "L\"" : "\"")
73 << FixItHint::CreateInsertion(EndLoc, "\"");
74 return;
75 }
76
77 if (getLangOpts().CPlusPlus11) {
78 Diag << FixItHint::CreateInsertion(Loc, IsWideCharType ? "std::to_wstring("
79 : "std::to_string(")
80 << FixItHint::CreateInsertion(EndLoc, ")");
81 }
82 }
83
84 } // namespace misc
85 } // namespace tidy
86 } // namespace clang
Loc
SourceLocation Loc
&#39;#&#39; location in the include directive
Definition: IncludeOrderCheck.cpp:36
Argument
This class represents one callback function argument by name and value.
Definition: PPCallbacksTracker.h:36
clang::ast_matchers
Definition: ClangTidyDiagnosticConsumer.h:27
StringIntegerAssignmentCheck.h
clang
Definition: AndroidTidyModule.cpp:28