11 #include "clang/AST/ASTContext.h" 12 #include "clang/AST/RecursiveASTVisitor.h" 13 #include "clang/ASTMatchers/ASTMatchFinder.h" 14 #include "clang/ASTMatchers/ASTMatchers.h" 15 #include "clang/Frontend/CompilerInstance.h" 16 #include "clang/Lex/Lexer.h" 17 #include "clang/Lex/Preprocessor.h" 41 for (
const CXXConstructorDecl *Ctor : Node.ctors()) {
42 if (Ctor->isMoveConstructor() && !Ctor->isDeleted())
49 return lValueReferenceType(pointee(isConstQualified()));
53 return qualType(unless(anyOf(referenceType(), isConstQualified())));
60 const ParmVarDecl *ParamDecl) {
65 class ExactlyOneUsageVisitor
66 :
public RecursiveASTVisitor<ExactlyOneUsageVisitor> {
67 friend class RecursiveASTVisitor<ExactlyOneUsageVisitor>;
70 ExactlyOneUsageVisitor(
const ParmVarDecl *ParamDecl)
71 : ParamDecl(ParamDecl) {}
76 bool hasExactlyOneUsageIn(
const CXXConstructorDecl *Ctor) {
78 TraverseDecl(const_cast<CXXConstructorDecl *>(Ctor));
86 bool VisitDeclRefExpr(DeclRefExpr *D) {
87 if (
const ParmVarDecl *To = dyn_cast<ParmVarDecl>(D->getDecl())) {
88 if (To == ParamDecl) {
99 const ParmVarDecl *ParamDecl;
103 return ExactlyOneUsageVisitor(ParamDecl).hasExactlyOneUsageIn(Ctor);
108 static SmallVector<const ParmVarDecl *, 2>
110 const ParmVarDecl *ParamDecl) {
111 SmallVector<const ParmVarDecl *, 2> Results;
112 unsigned ParamIdx = ParamDecl->getFunctionScopeIndex();
114 for (
const FunctionDecl *Redecl : Ctor->redecls())
115 Results.push_back(Redecl->getParamDecl(ParamIdx));
121 IncludeStyle(utils::IncludeSorter::parseIncludeStyle(
122 Options.getLocalOrGlobal(
"IncludeStyle",
"llvm"))),
123 ValuesOnly(Options.get(
"ValuesOnly", 0) != 0) {}
139 forEachConstructorInitializer(
141 unless(isBaseInitializer()),
146 withInitializer(cxxConstructExpr(
147 has(ignoringParenImpCasts(declRefExpr(to(
157 hasDeclaration(cxxConstructorDecl(
158 isCopyConstructor(), unless(isDeleted()),
160 cxxRecordDecl(isMoveConstructible())))))))
161 .bind(
"Initializer")))
172 Compiler.getSourceManager(), Compiler.getLangOpts(), IncludeStyle));
173 Compiler.getPreprocessor().addPPCallbacks(Inserter->CreatePPCallbacks());
178 const auto *Ctor = Result.Nodes.getNodeAs<CXXConstructorDecl>(
"Ctor");
179 const auto *ParamDecl = Result.Nodes.getNodeAs<ParmVarDecl>(
"Param");
180 const auto *Initializer =
181 Result.Nodes.getNodeAs<CXXCtorInitializer>(
"Initializer");
182 SourceManager &SM = *Result.SourceManager;
191 if (ParamDecl->getType().getNonReferenceType().isTriviallyCopyableType(
195 auto Diag =
diag(ParamDecl->getLocStart(),
"pass by value and use std::move");
199 auto ParamTL = ParmDecl->getTypeSourceInfo()->getTypeLoc();
200 auto RefTL = ParamTL.getAs<ReferenceTypeLoc>();
206 TypeLoc ValueTL = RefTL.getPointeeLoc();
207 auto TypeRange = CharSourceRange::getTokenRange(ParmDecl->getLocStart(),
208 ParamTL.getLocEnd());
209 std::string ValueStr = Lexer::getSourceText(CharSourceRange::getTokenRange(
210 ValueTL.getSourceRange()),
214 Diag << FixItHint::CreateReplacement(TypeRange, ValueStr);
218 Diag << FixItHint::CreateInsertion(Initializer->getRParenLoc(),
")")
219 << FixItHint::CreateInsertion(
220 Initializer->getLParenLoc().getLocWithOffset(1),
"std::move(");
222 if (
auto IncludeFixit = Inserter->CreateIncludeInsertion(
223 Result.SourceManager->getFileID(Initializer->getSourceLocation()),
226 Diag << *IncludeFixit;
static bool paramReferredExactlyOnce(const CXXConstructorDecl *Ctor, const ParmVarDecl *ParamDecl)
Whether or not ParamDecl is used exactly one time in Ctor.
void store(ClangTidyOptions::OptionMap &Options, StringRef LocalName, StringRef Value) const
Stores an option with the check-local name LocalName with string value Value to Options.
static TypeMatcher constRefType()
LangOptions getLangOpts() const
Returns the language options from the context.
static StringRef toString(IncludeStyle Style)
Converts IncludeStyle to string representation.
static TypeMatcher nonConstValueType()
Base class for all clang-tidy checks.
void registerPPCallbacks(clang::CompilerInstance &Compiler) override
std::map< std::string, std::string > OptionMap
void registerMatchers(ast_matchers::MatchFinder *Finder) override
Override this to register AST matchers with Finder.
static SmallVector< const ParmVarDecl *, 2 > collectParamDecls(const CXXConstructorDecl *Ctor, const ParmVarDecl *ParamDecl)
Find all references to ParamDecl across all of the redeclarations of Ctor.
Produces fixes to insert specified includes to source files, if not yet present.
Every ClangTidyCheck reports errors through a DiagnosticsEngine provided by this context.
void check(const ast_matchers::MatchFinder::MatchResult &Result) override
ClangTidyChecks that register ASTMatchers should do the actual work in here.
AST_MATCHER(VarDecl, isAsm)
void storeOptions(ClangTidyOptions::OptionMap &Opts) override
Should store all options supported by this check with their current values or default values for opti...
DiagnosticBuilder diag(SourceLocation Loc, StringRef Description, DiagnosticIDs::Level Level=DiagnosticIDs::Warning)
Add a diagnostic with the check's name.