10 #include "clang/AST/ASTContext.h"
11 #include "clang/ASTMatchers/ASTMatchFinder.h"
12 #include "clang/Frontend/CompilerInstance.h"
13 #include "clang/Lex/Lexer.h"
14 #include "clang/Lex/Preprocessor.h"
16 using namespace clang;
24 static const char AutoPtrTokenId[] =
"AutoPrTokenId";
25 static const char AutoPtrOwnershipTransferId[] =
"AutoPtrOwnershipTransferId";
36 AST_MATCHER(Expr, isLValue) {
return Node.getValueKind() == VK_LValue; }
59 const DeclContext *D = Node.getDeclContext();
61 while (D->isInlineNamespace())
64 if (!D->isNamespace() || !D->getParent()->isTranslationUnit())
67 const IdentifierInfo *
Info = cast<NamespaceDecl>(D)->getIdentifier();
69 return (Info &&
Info->isStr(
"std"));
74 ReplaceAutoPtrCheck::ReplaceAutoPtrCheck(StringRef
Name,
75 ClangTidyContext *Context)
76 : ClangTidyCheck(
Name, Context),
77 IncludeStyle(Options.getLocalOrGlobal(
"IncludeStyle",
78 utils::IncludeSorter::IS_LLVM)) {}
80 void ReplaceAutoPtrCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
81 Options.store(Opts,
"IncludeStyle", IncludeStyle);
84 void ReplaceAutoPtrCheck::registerMatchers(MatchFinder *Finder) {
85 auto AutoPtrDecl = recordDecl(hasName(
"auto_ptr"), isFromStdNamespace());
86 auto AutoPtrType = qualType(hasDeclaration(AutoPtrDecl));
96 Finder->addMatcher(typeLoc(loc(qualType(AutoPtrType,
99 unless(elaboratedType()))))
100 .bind(AutoPtrTokenId),
105 Finder->addMatcher(usingDecl(hasAnyUsingShadowDecl(hasTargetDecl(namedDecl(
106 hasName(
"auto_ptr"), isFromStdNamespace()))))
107 .bind(AutoPtrTokenId),
116 auto MovableArgumentMatcher =
117 expr(isLValue(), hasType(AutoPtrType)).bind(AutoPtrOwnershipTransferId);
120 cxxOperatorCallExpr(hasOverloadedOperatorName(
"="),
121 callee(cxxMethodDecl(ofClass(AutoPtrDecl))),
122 hasArgument(1, MovableArgumentMatcher)),
125 traverse(ast_type_traits::TK_AsIs,
126 cxxConstructExpr(hasType(AutoPtrType), argumentCountIs(1),
127 hasArgument(0, MovableArgumentMatcher))),
131 void ReplaceAutoPtrCheck::registerPPCallbacks(
const SourceManager &SM,
133 Preprocessor *ModuleExpanderPP) {
134 Inserter = std::make_unique<utils::IncludeInserter>(SM, getLangOpts(),
136 PP->addPPCallbacks(Inserter->CreatePPCallbacks());
139 void ReplaceAutoPtrCheck::check(
const MatchFinder::MatchResult &Result) {
140 SourceManager &SM = *Result.SourceManager;
142 Result.Nodes.getNodeAs<Expr>(AutoPtrOwnershipTransferId)) {
143 CharSourceRange
Range = Lexer::makeFileCharRange(
144 CharSourceRange::getTokenRange(
E->getSourceRange()), SM, LangOptions());
146 if (
Range.isInvalid())
150 diag(
Range.getBegin(),
"use std::move to transfer ownership")
151 << FixItHint::CreateInsertion(
Range.getBegin(),
"std::move(")
152 << FixItHint::CreateInsertion(
Range.getEnd(),
")")
153 << Inserter->CreateIncludeInsertion(SM.getMainFileID(),
"utility",
159 SourceLocation AutoPtrLoc;
160 if (
const auto *TL = Result.Nodes.getNodeAs<TypeLoc>(AutoPtrTokenId)) {
163 if (
auto Loc = TL->getAs<TemplateSpecializationTypeLoc>())
164 AutoPtrLoc =
Loc.getTemplateNameLoc();
165 }
else if (
const auto *D =
166 Result.Nodes.getNodeAs<UsingDecl>(AutoPtrTokenId)) {
169 AutoPtrLoc = D->getNameInfo().getBeginLoc();
171 llvm_unreachable(
"Bad Callback. No node provided.");
174 if (AutoPtrLoc.isMacroID())
175 AutoPtrLoc = SM.getSpellingLoc(AutoPtrLoc);
179 if (StringRef(SM.getCharacterData(AutoPtrLoc), strlen(
"auto_ptr")) !=
183 SourceLocation EndLoc =
184 AutoPtrLoc.getLocWithOffset(strlen(
"auto_ptr") - 1);
185 diag(AutoPtrLoc,
"auto_ptr is deprecated, use unique_ptr instead")
186 << FixItHint::CreateReplacement(SourceRange(AutoPtrLoc, EndLoc),