10 #include "clang/AST/ASTContext.h"
11 #include "clang/AST/RecursiveASTVisitor.h"
12 #include "clang/ASTMatchers/ASTMatchFinder.h"
13 #include "clang/ASTMatchers/ASTMatchers.h"
14 #include "clang/Frontend/CompilerInstance.h"
15 #include "clang/Lex/Lexer.h"
16 #include "clang/Lex/Preprocessor.h"
41 for (
const CXXConstructorDecl *Ctor : Node.ctors()) {
42 if (Ctor->isMoveConstructor() && !Ctor->isDeleted())
50 return lValueReferenceType(
51 pointee(unless(templateSpecializationType()), isConstQualified()));
55 return qualType(unless(anyOf(referenceType(), isConstQualified())));
62 const ParmVarDecl *ParamDecl) {
67 class ExactlyOneUsageVisitor
68 :
public RecursiveASTVisitor<ExactlyOneUsageVisitor> {
69 friend class RecursiveASTVisitor<ExactlyOneUsageVisitor>;
72 ExactlyOneUsageVisitor(
const ParmVarDecl *ParamDecl)
73 : ParamDecl(ParamDecl) {}
78 bool hasExactlyOneUsageIn(
const CXXConstructorDecl *Ctor) {
80 TraverseDecl(const_cast<CXXConstructorDecl *>(Ctor));
88 bool VisitDeclRefExpr(DeclRefExpr *D) {
89 if (
const ParmVarDecl *To = dyn_cast<ParmVarDecl>(D->getDecl())) {
90 if (To == ParamDecl) {
101 const ParmVarDecl *ParamDecl;
105 return ExactlyOneUsageVisitor(ParamDecl).hasExactlyOneUsageIn(Ctor);
110 static SmallVector<const ParmVarDecl *, 2>
112 const ParmVarDecl *ParamDecl) {
113 SmallVector<const ParmVarDecl *, 2>
Results;
114 unsigned ParamIdx = ParamDecl->getFunctionScopeIndex();
116 for (
const FunctionDecl *Redecl : Ctor->redecls())
117 Results.push_back(Redecl->getParamDecl(ParamIdx));
123 IncludeStyle(Options.getLocalOrGlobal(
"IncludeStyle",
124 utils::IncludeSorter::IS_LLVM)),
125 ValuesOnly(Options.get(
"ValuesOnly", false)) {}
135 ast_type_traits::TK_AsIs,
137 forEachConstructorInitializer(
139 unless(isBaseInitializer()),
145 withInitializer(cxxConstructExpr(
146 has(ignoringParenImpCasts(declRefExpr(to(
158 hasDeclaration(cxxConstructorDecl(
159 isCopyConstructor(), unless(isDeleted()),
161 cxxRecordDecl(isMoveConstructible())))))))
162 .bind(
"Initializer")))
169 Preprocessor *ModuleExpanderPP) {
170 Inserter = std::make_unique<utils::IncludeInserter>(SM,
getLangOpts(),
172 PP->addPPCallbacks(Inserter->CreatePPCallbacks());
176 const auto *Ctor = Result.Nodes.getNodeAs<CXXConstructorDecl>(
"Ctor");
177 const auto *ParamDecl = Result.Nodes.getNodeAs<ParmVarDecl>(
"Param");
178 const auto *Initializer =
179 Result.Nodes.getNodeAs<CXXCtorInitializer>(
"Initializer");
180 SourceManager &SM = *Result.SourceManager;
189 if (ParamDecl->getType().getNonReferenceType().isTriviallyCopyableType(
193 auto Diag =
diag(ParamDecl->getBeginLoc(),
"pass by value and use std::move");
197 auto ParamTL = ParmDecl->getTypeSourceInfo()->getTypeLoc();
198 auto RefTL = ParamTL.getAs<ReferenceTypeLoc>();
204 TypeLoc ValueTL = RefTL.getPointeeLoc();
205 auto TypeRange = CharSourceRange::getTokenRange(ParmDecl->getBeginLoc(),
206 ParamTL.getEndLoc());
207 std::string ValueStr = Lexer::getSourceText(CharSourceRange::getTokenRange(
208 ValueTL.getSourceRange()),
212 Diag << FixItHint::CreateReplacement(TypeRange, ValueStr);
216 Diag << FixItHint::CreateInsertion(Initializer->getRParenLoc(),
")")
217 << FixItHint::CreateInsertion(
218 Initializer->getLParenLoc().getLocWithOffset(1),
"std::move(")
219 << Inserter->CreateIncludeInsertion(
220 Result.SourceManager->getFileID(Initializer->getSourceLocation()),