1 //===--- TwineLocalCheck.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 "TwineLocalCheck.h" 11 #include "clang/AST/ASTContext.h" 12 #include "clang/ASTMatchers/ASTMatchers.h" 13 #include "clang/Lex/Lexer.h" 14 15 using namespace clang::ast_matchers; 16 17 namespace clang { 18 namespace tidy { 19 20 void TwineLocalCheck::registerMatchers(MatchFinder *Finder) { 21 auto TwineType = 22 qualType(hasDeclaration(recordDecl(hasName("::llvm::Twine")))); 23 Finder->addMatcher(varDecl(hasType(TwineType)).bind("variable"), this); 24 } 25 26 void TwineLocalCheck::check(const MatchFinder::MatchResult &Result) { 27 const VarDecl *VD = Result.Nodes.getNodeAs<VarDecl>("variable"); 28 auto Diag = diag(VD->getLocation(), 29 "twine variables are prone to use-after-free bugs"); 30 31 // If this VarDecl has an initializer try to fix it. 32 if (VD->hasInit()) { 33 // Peel away implicit constructors and casts so we can see the actual type 34 // of the initializer. 35 const Expr *C = VD->getInit(); 36 while (isa<CXXConstructExpr>(C)) 37 C = cast<CXXConstructExpr>(C)->getArg(0)->IgnoreParenImpCasts(); 38 39 SourceRange TypeRange = 40 VD->getTypeSourceInfo()->getTypeLoc().getSourceRange(); 41 42 // A real Twine, turn it into a std::string. 43 if (VD->getType()->getCanonicalTypeUnqualified() == 44 C->getType()->getCanonicalTypeUnqualified()) { 45 SourceLocation EndLoc = Lexer::getLocForEndOfToken( 46 VD->getInit()->getLocEnd(), 0, *Result.SourceManager, 47 Result.Context->getLangOpts()); 48 Diag << FixItHint::CreateReplacement(TypeRange, "std::string") 49 << FixItHint::CreateInsertion(VD->getInit()->getLocStart(), "(") 50 << FixItHint::CreateInsertion(EndLoc, ").str()"); 51 } else { 52 // Just an implicit conversion. Insert the real type. 53 Diag << FixItHint::CreateReplacement( 54 TypeRange, 55 C->getType().getAsString(Result.Context->getPrintingPolicy())); 56 } 57 } 58 } 59 60 } // namespace tidy 61 } // namespace clang 62