10 #include "../utils/Matchers.h"
11 #include "clang/AST/ASTContext.h"
12 #include "clang/ASTMatchers/ASTMatchFinder.h"
13 #include "clang/Frontend/CompilerInstance.h"
14 #include "clang/Lex/Lexer.h"
15 #include "clang/Lex/Preprocessor.h"
21 namespace performance {
23 MoveConstructorInitCheck::MoveConstructorInitCheck(StringRef
Name,
26 IncludeStyle(Options.getLocalOrGlobal(
"IncludeStyle",
27 utils::IncludeSorter::IS_LLVM)) {}
31 traverse(ast_type_traits::TK_AsIs,
33 unless(isImplicit()), isMoveConstructor(),
34 hasAnyConstructorInitializer(
36 withInitializer(cxxConstructExpr(hasDeclaration(
37 cxxConstructorDecl(isCopyConstructor())
39 .bind(
"move-init")))),
44 const auto *CopyCtor = Result.Nodes.getNodeAs<CXXConstructorDecl>(
"ctor");
45 const auto *Initializer =
46 Result.Nodes.getNodeAs<CXXCtorInitializer>(
"move-init");
50 QualType QT = Initializer->getInit()->getType();
51 if (QT.isTriviallyCopyableType(*Result.Context))
54 if (QT.isConstQualified())
57 const auto *RD = QT->getAsCXXRecordDecl();
58 if (RD && RD->isTriviallyCopyable())
63 const CXXConstructorDecl *
Candidate =
nullptr;
64 for (
const auto *Ctor : CopyCtor->getParent()->ctors()) {
65 if (Ctor->isMoveConstructor() && Ctor->getAccess() <= AS_protected &&
81 diag(Initializer->getSourceLocation(),
82 "move constructor initializes %0 by calling a copy constructor")
83 << (Initializer->isBaseInitializer() ?
"base class" :
"class member");
84 diag(CopyCtor->getLocation(),
"copy constructor being called",
86 diag(
Candidate->getLocation(),
"candidate move constructor here",
92 const SourceManager &SM, Preprocessor *
PP, Preprocessor *ModuleExpanderPP) {
93 Inserter = std::make_unique<utils::IncludeInserter>(SM,
getLangOpts(),
95 PP->addPPCallbacks(Inserter->CreatePPCallbacks());