void StaticObjectExceptionCheck::registerMatchers(MatchFinder *Finder) {
  if ((!getLangOpts().CPlusPlus) || (!getLangOpts().CXXExceptions))
    return;

  // Match any static or thread_local variable declaration that has an
  // initializer that can throw.
  Finder->addMatcher(
      varDecl(anyOf(hasThreadStorageDuration(), hasStaticStorageDuration()),
              unless(anyOf(isConstexpr(), hasType(cxxRecordDecl(isLambda())),
                           hasAncestor(functionDecl()))),
              anyOf(hasDescendant(cxxConstructExpr(hasDeclaration(
                        cxxConstructorDecl(unless(isNoThrow())).bind("func")))),
                    hasDescendant(cxxNewExpr(hasDeclaration(
                        functionDecl(unless(isNoThrow())).bind("func")))),
                    hasDescendant(callExpr(hasDeclaration(
                        functionDecl(unless(isNoThrow())).bind("func"))))))
          .bind("var"),
      this);
}
void ThrownExceptionTypeCheck::registerMatchers(MatchFinder *Finder) {
  if (!getLangOpts().CPlusPlus)
    return;

  Finder->addMatcher(
      cxxThrowExpr(has(ignoringParenImpCasts(
          cxxConstructExpr(hasDeclaration(cxxConstructorDecl(
                               isCopyConstructor(), unless(isNoThrow()))))
              .bind("expr")))),
      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);
}