clang-tools  13.0.0git
MoveConstructorInitCheck.cpp
Go to the documentation of this file.
1 //===--- MoveConstructorInitCheck.cpp - clang-tidy-------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
10 #include "../utils/Matchers.h"
11 #include "clang/AST/ASTContext.h"
12 #include "clang/ASTMatchers/ASTMatchFinder.h"
13 
14 using namespace clang::ast_matchers;
15 
16 namespace clang {
17 namespace tidy {
18 namespace performance {
19 
20 MoveConstructorInitCheck::MoveConstructorInitCheck(StringRef Name,
21  ClangTidyContext *Context)
22  : ClangTidyCheck(Name, Context) {}
23 
24 void MoveConstructorInitCheck::registerMatchers(MatchFinder *Finder) {
25  Finder->addMatcher(
26  traverse(TK_AsIs,
27  cxxConstructorDecl(
28  unless(isImplicit()), isMoveConstructor(),
29  hasAnyConstructorInitializer(
30  cxxCtorInitializer(
31  withInitializer(cxxConstructExpr(hasDeclaration(
32  cxxConstructorDecl(isCopyConstructor())
33  .bind("ctor")))))
34  .bind("move-init")))),
35  this);
36 }
37 
38 void MoveConstructorInitCheck::check(const MatchFinder::MatchResult &Result) {
39  const auto *CopyCtor = Result.Nodes.getNodeAs<CXXConstructorDecl>("ctor");
40  const auto *Initializer =
41  Result.Nodes.getNodeAs<CXXCtorInitializer>("move-init");
42 
43  // Do not diagnose if the expression used to perform the initialization is a
44  // trivially-copyable type.
45  QualType QT = Initializer->getInit()->getType();
46  if (QT.isTriviallyCopyableType(*Result.Context))
47  return;
48 
49  if (QT.isConstQualified())
50  return;
51 
52  const auto *RD = QT->getAsCXXRecordDecl();
53  if (RD && RD->isTriviallyCopyable())
54  return;
55 
56  // Diagnose when the class type has a move constructor available, but the
57  // ctor-initializer uses the copy constructor instead.
58  const CXXConstructorDecl *Candidate = nullptr;
59  for (const auto *Ctor : CopyCtor->getParent()->ctors()) {
60  if (Ctor->isMoveConstructor() && Ctor->getAccess() <= AS_protected &&
61  !Ctor->isDeleted()) {
62  // The type has a move constructor that is at least accessible to the
63  // initializer.
64  //
65  // FIXME: Determine whether the move constructor is a viable candidate
66  // for the ctor-initializer, perhaps provide a fix-it that suggests
67  // using std::move().
68  Candidate = Ctor;
69  break;
70  }
71  }
72 
73  if (Candidate) {
74  // There's a move constructor candidate that the caller probably intended
75  // to call instead.
76  diag(Initializer->getSourceLocation(),
77  "move constructor initializes %select{class member|base class}0 by "
78  "calling a copy constructor")
79  << Initializer->isBaseInitializer();
80  diag(CopyCtor->getLocation(), "copy constructor being called",
81  DiagnosticIDs::Note);
82  diag(Candidate->getLocation(), "candidate move constructor here",
83  DiagnosticIDs::Note);
84  }
85 }
86 
87 } // namespace performance
88 } // namespace tidy
89 } // namespace clang
clang::tidy::ClangTidyCheck
Base class for all clang-tidy checks.
Definition: ClangTidyCheck.h:54
clang::ast_matchers
Definition: AbseilMatcher.h:14
clang::tidy::ClangTidyContext
Every ClangTidyCheck reports errors through a DiagnosticsEngine provided by this context.
Definition: ClangTidyDiagnosticConsumer.h:76
Name
static constexpr llvm::StringLiteral Name
Definition: UppercaseLiteralSuffixCheck.cpp:27
clang::tidy::performance::MoveConstructorInitCheck::registerMatchers
void registerMatchers(ast_matchers::MatchFinder *Finder) override
Override this to register AST matchers with Finder.
Definition: MoveConstructorInitCheck.cpp:24
clang::tidy::ClangTidyCheck::diag
DiagnosticBuilder diag(SourceLocation Loc, StringRef Description, DiagnosticIDs::Level Level=DiagnosticIDs::Warning)
Add a diagnostic with the check's name.
Definition: ClangTidyCheck.cpp:25
MoveConstructorInitCheck.h
Candidate
ExpectedMatch Candidate
Definition: FuzzyMatchTests.cpp:47
clang
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
Definition: ApplyReplacements.h:27
clang::tidy::performance::MoveConstructorInitCheck::check
void check(const ast_matchers::MatchFinder::MatchResult &Result) override
ClangTidyChecks that register ASTMatchers should do the actual work in here.
Definition: MoveConstructorInitCheck.cpp:38