summaryrefslogtreecommitdiffstats
path: root/clang-tools-extra/clang-tidy/modernize/UseDefaultCheck.cpp
blob: 829371b3e1e978081000858ee862455d16b9c86c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
//===--- UseDefaultCheck.cpp - clang-tidy----------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "UseDefaultCheck.h"
#include "clang/AST/ASTContext.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"

using namespace clang::ast_matchers;

namespace clang {
namespace tidy {
namespace modernize {

static const char CtorDtor[] = "CtorDtorDecl";

void UseDefaultCheck::registerMatchers(MatchFinder *Finder) {
  if (getLangOpts().CPlusPlus) {
    Finder->addMatcher(
        cxxConstructorDecl(isDefinition(),
                           unless(hasAnyConstructorInitializer(anything())),
                           parameterCountIs(0))
            .bind(CtorDtor),
        this);
    Finder->addMatcher(cxxDestructorDecl(isDefinition()).bind(CtorDtor), this);
  }
}

void UseDefaultCheck::check(const MatchFinder::MatchResult &Result) {
  // Both CXXConstructorDecl and CXXDestructorDecl inherit from CXXMethodDecl.
  const auto *CtorDtorDecl = Result.Nodes.getNodeAs<CXXMethodDecl>(CtorDtor);

  // Discard explicitly deleted/defaulted constructors/destructors, those that
  // are not user-provided (automatically generated constructor/destructor), and
  // those with non-empty bodies.
  if (CtorDtorDecl->isDeleted() || CtorDtorDecl->isExplicitlyDefaulted() ||
      !CtorDtorDecl->isUserProvided() || !CtorDtorDecl->hasTrivialBody())
    return;

  const auto *Body = dyn_cast<CompoundStmt>(CtorDtorDecl->getBody());
  // This should never happen, since 'hasTrivialBody' checks that this is
  // actually a CompoundStmt.
  assert(Body && "Definition body is not a CompoundStmt");

  diag(CtorDtorDecl->getLocStart(),
       "use '= default' to define a trivial " +
           std::string(dyn_cast<CXXConstructorDecl>(CtorDtorDecl)
                           ? "default constructor"
                           : "destructor"))
      << FixItHint::CreateReplacement(
          CharSourceRange::getTokenRange(Body->getLBracLoc(),
                                         Body->getRBracLoc()),
          "= default;");
}

} // namespace modernize
} // namespace tidy
} // namespace clang
OpenPOWER on IntegriCloud