clang-tools  3.9.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 
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,
66  Result.Context->getLangOpts());
67  if (IsOneDigit) {
68  Diag << FixItHint::CreateInsertion(Loc, IsWideCharType ? "L'" : "'")
69  << FixItHint::CreateInsertion(EndLoc, "'");
70  return;
71  }
72  if (IsLiteral) {
73  Diag << FixItHint::CreateInsertion(Loc, IsWideCharType ? "L\"" : "\"")
74  << FixItHint::CreateInsertion(EndLoc, "\"");
75  return;
76  }
77 
78  if (getLangOpts().CPlusPlus11) {
79  Diag << FixItHint::CreateInsertion(Loc, IsWideCharType ? "std::to_wstring("
80  : "std::to_string(")
81  << FixItHint::CreateInsertion(EndLoc, ")");
82  }
83 }
84 
85 } // namespace misc
86 } // namespace tidy
87 } // namespace clang
SourceLocation Loc
'#' location in the include directive
This class represents one callback function argument by name and value.
std::unique_ptr< ast_matchers::MatchFinder > Finder
Definition: ClangTidy.cpp:210
const NamedDecl * Result
Definition: USRFinder.cpp:137