clang-tools  8.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 
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 bugprone {
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->getBeginLoc();
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->getEndLoc(), 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 bugprone
85 } // namespace tidy
86 } // namespace clang
SourceLocation Loc
&#39;#&#39; location in the include directive
This class represents one callback function argument by name and value.
llvm::Optional< llvm::Expected< tooling::AtomicChanges > > Result
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//