void RedundantVoidArgCheck::registerMatchers(MatchFinder *Finder) {
  Finder->addMatcher(functionDecl(parameterCountIs(0), unless(isImplicit()),
                                  unless(isExternC()))
                         .bind(FunctionId),
                     this);
  Finder->addMatcher(typedefNameDecl().bind(TypedefId), this);
  auto ParenFunctionType = parenType(innerType(functionType()));
  auto PointerToFunctionType = pointee(ParenFunctionType);
  auto FunctionOrMemberPointer =
      anyOf(hasType(pointerType(PointerToFunctionType)),
            hasType(memberPointerType(PointerToFunctionType)));
  Finder->addMatcher(fieldDecl(FunctionOrMemberPointer).bind(FieldId), this);
  Finder->addMatcher(varDecl(FunctionOrMemberPointer).bind(VarId), this);
  auto CastDestinationIsFunction =
      hasDestinationType(pointsTo(ParenFunctionType));
  Finder->addMatcher(
      cStyleCastExpr(CastDestinationIsFunction).bind(CStyleCastId), this);
  Finder->addMatcher(
      cxxStaticCastExpr(CastDestinationIsFunction).bind(NamedCastId), this);
  Finder->addMatcher(
      cxxReinterpretCastExpr(CastDestinationIsFunction).bind(NamedCastId),
      this);
  Finder->addMatcher(
      cxxConstCastExpr(CastDestinationIsFunction).bind(NamedCastId), this);
  Finder->addMatcher(lambdaExpr().bind(LambdaId), this);
}
void CanRunScriptChecker::buildFuncSet(ASTContext *Context) {
  // We create a match finder.
  MatchFinder Finder;
  // We create the callback which will be called when we find a function with
  // a MOZ_CAN_RUN_SCRIPT annotation.
  FuncSetCallback Callback(CanRunScriptFuncs);
  // We add the matcher to the finder, linking it to our callback.
  Finder.addMatcher(
      functionDecl(hasCanRunScriptAnnotation()).bind("canRunScriptFunction"),
      &Callback);
  Finder.addMatcher(
      lambdaExpr().bind("lambda"),
      &Callback);
  // We start the analysis, given the ASTContext our main checker is in.
  Finder.matchAST(*Context);
}
void DanglingOnTemporaryChecker::registerMatchers(MatchFinder *AstMatcher) {
  ////////////////////////////////////////
  // Quick annotation conflict checkers //
  ////////////////////////////////////////

  AstMatcher->addMatcher(
      // This is a matcher on a method declaration,
      cxxMethodDecl(
          // which is marked as no dangling on temporaries,
          noDanglingOnTemporaries(),

          // and which is && ref-qualified.
          isRValueRefQualified(),

          decl().bind("invalidMethodRefQualified")),
      this);

  AstMatcher->addMatcher(
      // This is a matcher on a method declaration,
      cxxMethodDecl(
          // which is marked as no dangling on temporaries,
          noDanglingOnTemporaries(),

          // which returns a primitive type,
          returns(builtinType()),

          // and which doesn't return a pointer.
          unless(returns(pointerType())),

          decl().bind("invalidMethodPointer")),
      this);

  //////////////////
  // Main checker //
  //////////////////

  auto hasParentCall =
      hasParent(expr(anyOf(
          cxxOperatorCallExpr(
              // If we're in a lamda, we may have an operator call expression
              // ancestor in the AST, but the temporary we're matching
              // against is not going to have the same lifetime as the
              // constructor call.
              unless(has(expr(ignoreTrivials(lambdaExpr())))),
              expr().bind("parentOperatorCallExpr")),
          callExpr(
              // If we're in a lamda, we may have a call expression
              // ancestor in the AST, but the temporary we're matching
              // against is not going to have the same lifetime as the
              // function call.
              unless(has(expr(ignoreTrivials(lambdaExpr())))),
              expr().bind("parentCallExpr")),
          objcMessageExpr(
              // If we're in a lamda, we may have an objc message expression
              // ancestor in the AST, but the temporary we're matching
              // against is not going to have the same lifetime as the
              // function call.
              unless(has(expr(ignoreTrivials(lambdaExpr())))),
              expr().bind("parentObjCMessageExpr")),
          cxxConstructExpr(
              // If we're in a lamda, we may have a construct expression
              // ancestor in the AST, but the temporary we're matching
              // against is not going to have the same lifetime as the
              // constructor call.
              unless(has(expr(ignoreTrivials(lambdaExpr())))),
              expr().bind("parentConstructExpr")))));

  AstMatcher->addMatcher(
      // This is a matcher on a method call,
      cxxMemberCallExpr(
          // which is in first party code,
          isFirstParty(),

          // and which is performed on a temporary,
          on(allOf(
              unless(hasType(pointerType())),
              isTemporary(),
              // but which is not `this`.
              unless(cxxThisExpr()))),

          // and which is marked as no dangling on temporaries.
          callee(cxxMethodDecl(noDanglingOnTemporaries())),

          expr().bind("memberCallExpr"),

          // We optionally match a parent call expression or a parent construct
          // expression because using a temporary inside a call is fine as long
          // as the pointer doesn't escape the function call.
          anyOf(
              // This is the case where the call is the direct parent, so we
              // know that the member call expression is the argument.
              allOf(hasParentCall, expr().bind("parentCallArg")),

              // This is the case where the call is not the direct parent, so we
              // get its child to know in which argument tree we are.
              hasAncestor(expr(
                  hasParentCall,
                  expr().bind("parentCallArg"))),
              // To make it optional.
              anything())),
      this);
}
void LambdaFunctionNameCheck::registerMatchers(MatchFinder *Finder) {
  // Match on PredefinedExprs inside a lambda.
  Finder->addMatcher(predefinedExpr(hasAncestor(lambdaExpr())).bind("E"),
                     this);
}