llvm-project

Форк
0
/
UndelegatedConstructorCheck.cpp 
76 строк · 2.9 Кб
1
//===--- UndelegatedConstructorCheck.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

9
#include "UndelegatedConstructorCheck.h"
10
#include "clang/AST/ASTContext.h"
11
#include "clang/Lex/Lexer.h"
12

13
using namespace clang::ast_matchers;
14

15
namespace clang::tidy::bugprone {
16

17
namespace {
18
AST_MATCHER_P(Stmt, ignoringTemporaryExpr,
19
              ast_matchers::internal::Matcher<Stmt>, InnerMatcher) {
20
  const Stmt *E = &Node;
21
  for (;;) {
22
    // Temporaries with non-trivial dtors.
23
    if (const auto *EWC = dyn_cast<ExprWithCleanups>(E))
24
      E = EWC->getSubExpr();
25
    // Temporaries with zero or more than two ctor arguments.
26
    else if (const auto *BTE = dyn_cast<CXXBindTemporaryExpr>(E))
27
      E = BTE->getSubExpr();
28
    // Temporaries with exactly one ctor argument.
29
    else if (const auto *FCE = dyn_cast<CXXFunctionalCastExpr>(E))
30
      E = FCE->getSubExpr();
31
    else
32
      break;
33
  }
34

35
  return InnerMatcher.matches(*E, Finder, Builder);
36
}
37

38
// Finds a node if it's a base of an already bound node.
39
AST_MATCHER_P(CXXRecordDecl, baseOfBoundNode, std::string, ID) {
40
  return Builder->removeBindings(
41
      [&](const ast_matchers::internal::BoundNodesMap &Nodes) {
42
        const auto *Derived = Nodes.getNodeAs<CXXRecordDecl>(ID);
43
        return Derived != &Node && !Derived->isDerivedFrom(&Node);
44
      });
45
}
46
} // namespace
47

48
void UndelegatedConstructorCheck::registerMatchers(MatchFinder *Finder) {
49
  // We look for calls to constructors of the same type in constructors. To do
50
  // this we have to look through a variety of nodes that occur in the path,
51
  // depending on the type's destructor and the number of arguments on the
52
  // constructor call, this is handled by ignoringTemporaryExpr. Ignore template
53
  // instantiations to reduce the number of duplicated warnings.
54

55
  Finder->addMatcher(
56
      traverse(
57
          TK_AsIs,
58
          compoundStmt(hasParent(cxxConstructorDecl(
59
                           ofClass(cxxRecordDecl().bind("parent")))),
60
                       forEach(ignoringTemporaryExpr(
61
                           cxxConstructExpr(
62
                               hasDeclaration(cxxConstructorDecl(ofClass(
63
                                   cxxRecordDecl(baseOfBoundNode("parent"))))))
64
                               .bind("construct"))),
65
                       unless(isInTemplateInstantiation()))),
66
      this);
67
}
68

69
void UndelegatedConstructorCheck::check(
70
    const MatchFinder::MatchResult &Result) {
71
  const auto *E = Result.Nodes.getNodeAs<CXXConstructExpr>("construct");
72
  diag(E->getBeginLoc(), "did you intend to call a delegated constructor? "
73
                         "A temporary object is created here instead");
74
}
75

76
} // namespace clang::tidy::bugprone
77

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.