void UseEqualsDeleteCheck::registerMatchers(MatchFinder *Finder) {
  auto PrivateSpecialFn = cxxMethodDecl(
      isPrivate(),
      anyOf(cxxConstructorDecl(anyOf(isDefaultConstructor(),
                                     isCopyConstructor(), isMoveConstructor())),
            cxxMethodDecl(
                anyOf(isCopyAssignmentOperator(), isMoveAssignmentOperator())),
            cxxDestructorDecl()));

  Finder->addMatcher(
      cxxMethodDecl(
          PrivateSpecialFn,
          unless(anyOf(hasBody(stmt()), isDefaulted(), isDeleted(),
                       ast_matchers::isTemplateInstantiation(),
                       // Ensure that all methods except private special member
                       // functions are defined.
                       hasParent(cxxRecordDecl(hasMethod(unless(
                           anyOf(PrivateSpecialFn, hasBody(stmt()), isPure(),
                                 isDefaulted(), isDeleted()))))))))
          .bind(SpecialFunction),
      this);

  Finder->addMatcher(
      cxxMethodDecl(isDeleted(), unless(isPublic())).bind(DeletedNotPublic),
      this);
}
void ExceptionEscapeCheck::registerMatchers(MatchFinder *Finder) {
  if (!getLangOpts().CPlusPlus || !getLangOpts().CXXExceptions)
    return;

  Finder->addMatcher(
      functionDecl(anyOf(isNoThrow(), cxxDestructorDecl(),
                         cxxConstructorDecl(isMoveConstructor()),
                         cxxMethodDecl(isMoveAssignmentOperator()),
                         hasName("main"), hasName("swap"),
                         isEnabled(FunctionsThatShouldNotThrow)),
                   throws(unless(isIgnored(IgnoredExceptions))))
          .bind("thrower"),
      this);
}
Пример #3
0
void SlicingCheck::registerMatchers(MatchFinder *Finder) {
  // When we see:
  //   class B : public A { ... };
  //   A a;
  //   B b;
  //   a = b;
  // The assignment is OK if:
  //   - the assignment operator is defined as taking a B as second parameter,
  //   or
  //   - B does not define any additional members (either variables or
  //   overrides) wrt A.
  //
  // The same holds for copy ctor calls. This also captures stuff like:
  //   void f(A a);
  //   f(b);

  //  Helpers.
  const auto OfBaseClass = ofClass(cxxRecordDecl().bind("BaseDecl"));
  const auto IsDerivedFromBaseDecl =
      cxxRecordDecl(isDerivedFrom(equalsBoundNode("BaseDecl")))
          .bind("DerivedDecl");
  const auto HasTypeDerivedFromBaseDecl =
      anyOf(hasType(IsDerivedFromBaseDecl),
            hasType(references(IsDerivedFromBaseDecl)));
  const auto IsWithinDerivedCtor =
      hasParent(cxxConstructorDecl(ofClass(equalsBoundNode("DerivedDecl"))));

  // Assignement slicing: "a = b;" and "a = std::move(b);" variants.
  const auto SlicesObjectInAssignment =
      callExpr(callee(cxxMethodDecl(anyOf(isCopyAssignmentOperator(),
                                          isMoveAssignmentOperator()),
                                    OfBaseClass)),
               hasArgument(1, HasTypeDerivedFromBaseDecl));

  // Construction slicing: "A a{b};" and "f(b);" variants. Note that in case of
  // slicing the letter will create a temporary and therefore call a ctor.
  const auto SlicesObjectInCtor = cxxConstructExpr(
      hasDeclaration(cxxConstructorDecl(
          anyOf(isCopyConstructor(), isMoveConstructor()), OfBaseClass)),
      hasArgument(0, HasTypeDerivedFromBaseDecl),
      // We need to disable matching on the call to the base copy/move
      // constructor in DerivedDecl's constructors.
      unless(IsWithinDerivedCtor));

  Finder->addMatcher(
      expr(anyOf(SlicesObjectInAssignment, SlicesObjectInCtor)).bind("Call"),
      this);
}
void SpecialMemberFunctionsCheck::registerMatchers(MatchFinder *Finder) {
  if (!getLangOpts().CPlusPlus)
    return;
  Finder->addMatcher(
      cxxRecordDecl(
          eachOf(
              has(cxxDestructorDecl(unless(isImplicit())).bind("dtor")),
              has(cxxConstructorDecl(isCopyConstructor(), unless(isImplicit()))
                      .bind("copy-ctor")),
              has(cxxMethodDecl(isCopyAssignmentOperator(),
                                unless(isImplicit()))
                      .bind("copy-assign")),
              has(cxxConstructorDecl(isMoveConstructor(), unless(isImplicit()))
                      .bind("move-ctor")),
              has(cxxMethodDecl(isMoveAssignmentOperator(),
                                unless(isImplicit()))
                      .bind("move-assign"))))
          .bind("class-def"),
      this);
}