void SuspiciousEnumUsageCheck::registerMatchers(MatchFinder *Finder) {
  const auto enumExpr = [](StringRef RefName, StringRef DeclName) {
    return allOf(ignoringImpCasts(expr().bind(RefName)),
                 ignoringImpCasts(hasType(enumDecl().bind(DeclName))));
  };

  Finder->addMatcher(
      binaryOperator(hasOperatorName("|"), hasLHS(enumExpr("", "enumDecl")),
                     hasRHS(allOf(enumExpr("", "otherEnumDecl"),
                                  ignoringImpCasts(hasType(enumDecl(
                                      unless(equalsBoundNode("enumDecl"))))))))
          .bind("diffEnumOp"),
      this);

  Finder->addMatcher(
      binaryOperator(anyOf(hasOperatorName("+"), hasOperatorName("|")),
                     hasLHS(enumExpr("lhsExpr", "enumDecl")),
                     hasRHS(allOf(enumExpr("rhsExpr", ""),
                                  ignoringImpCasts(hasType(enumDecl(
                                      equalsBoundNode("enumDecl"))))))),
      this);

  Finder->addMatcher(
      binaryOperator(anyOf(hasOperatorName("+"), hasOperatorName("|")),
                     hasEitherOperand(
                         allOf(hasType(isInteger()), unless(enumExpr("", "")))),
                     hasEitherOperand(enumExpr("enumExpr", "enumDecl"))),
      this);

  Finder->addMatcher(
      binaryOperator(anyOf(hasOperatorName("|="), hasOperatorName("+=")),
                     hasRHS(enumExpr("enumExpr", "enumDecl"))),
      this);
}
#include "ASTUtility.h" 

//match sturct/union/class 
DeclarationMatcher enumDeclMatcher = enumDecl().bind("enumDecl");

class EnumDeclPrinter : public MatchFinder::MatchCallback {
public:
    virtual void run(const MatchFinder::MatchResult &Result) 
    {
        //get the node
        clang::ASTContext *Context = Result.Context;
        const clang::EnumDecl *enumerator = Result.Nodes.getNodeAs<clang::EnumDecl>("enumDecl");

        if(!enumerator || ASTUtility::IsDeclInSTDFile(enumerator, Context)) return; 

        if (!enumerator -> isScopedUsingClassTag())
            ASTUtility::Print(enumerator, Context, "Rule025");
    }
};

//"My tool options" is the name.
static llvm::cl::OptionCategory MyToolCategory("My tool options");

int main(int argc, const char **argv)
{
    //CommonOptionsParser constructor will parse arguments and create a
    //CompilationDatabase. In case of error it will terminate the program.
    CommonOptionsParser OptionsParser(argc, argv, MyToolCategory);
    //once we have a CompilationDatabase, we can create a ClangTool and run our
    //FrontendAction over some code.
    ClangTool Tool(OptionsParser.getCompilations(),