#include #include #include #include #include namespace clang { class MyTreeTransform : public TreeTransform { ASTContext& Context; public: MyTreeTransform(Sema& SemaRef, clang::ASTContext& Context) : TreeTransform(SemaRef), Context(Context) {} ExprResult TransformBinaryOperator(BinaryOperator* E) { llvm::outs() << "Transforming BinaryOperator\n"; E->dump(); auto LHS = TransformExpr(E->getLHS()); auto RHS = TransformExpr(E->getRHS()); return SemaRef.BuildBinOp(SemaRef.getCurScope(), E->getOperatorLoc(), E->getOpcode(), RHS.get(), LHS.get()); } ExprResult RebuildBinaryOperator(SourceLocation OpLoc, BinaryOperatorKind Opc, Expr* LHS, Expr* RHS) { llvm::outs() << "-----------------------------" << "\n"; return SemaRef.BuildBinOp(SemaRef.getCurScope(), OpLoc, Opc, RHS, LHS); } }; class ASTVisitor : public RecursiveASTVisitor { clang::ASTContext& Context; clang::Sema& SemaRef; public: public: ASTVisitor(clang::ASTContext& Context, clang::Sema& SemaRef) : Context(Context), SemaRef(SemaRef) {} bool VisitVarDecl(VarDecl* decl) { llvm::outs() << "Visiting BinaryOperator\n"; clang::MyTreeTransform transformer{SemaRef, Context}; decl->dump(); auto result = transformer.TransformExpr(decl->getInit()); decl->setInit(result.get()); decl->dump(); return true; } }; class MySemaConsumer : public clang::SemaConsumer { clang::CompilerInstance& CI; public: MySemaConsumer(clang::CompilerInstance& CI) : CI(CI) {} void HandleTranslationUnit(clang::ASTContext& Context) override { clang::Sema& SemaRef = CI.getSema(); clang::MyTreeTransform Transformer(SemaRef, Context); llvm::outs() << "------------------------------\n"; auto TU = Context.getTranslationUnitDecl(); clang::ASTVisitor visitor{Context, SemaRef}; visitor.TraverseDecl(TU); } }; class MyFrontendAction : public clang::ASTFrontendAction { public: std::unique_ptr CreateASTConsumer(clang::CompilerInstance& CI, llvm::StringRef) override { return std::make_unique(CI); } }; } // namespace clang int main(int argc, const char** argv) { assert(argc == 2 && "Usage: Preprocessor "); llvm::outs() << "running ASTVisitor...\n"; auto instance = std::make_unique(); clang::DiagnosticIDs* ids = new clang::DiagnosticIDs(); clang::DiagnosticOptions* diag_opts = new clang::DiagnosticOptions(); clang::DiagnosticConsumer* consumer = new clang::IgnoringDiagConsumer(); clang::DiagnosticsEngine* engine = new clang::DiagnosticsEngine(ids, diag_opts, consumer); instance->setDiagnostics(engine); auto invocation = std::make_shared(); std::vector args = { "/usr/local/bin/clang++", "-Xclang", "-no-round-trip-args", "-std=c++20", argv[1], }; invocation = clang::createInvocation(args, {}); // clang::CompilerInvocation::CreateFromArgs(*invocation, args, instance->getDiagnostics()); instance->setInvocation(std::move(invocation)); if(!instance->createTarget()) { llvm::errs() << "Failed to create target\n"; std::terminate(); } // instance->setASTConsumer(std::make_unique(*instance)); clang::MyFrontendAction action; if(!action.BeginSourceFile(*instance, instance->getFrontendOpts().Inputs[0])) { llvm::errs() << "Failed to begin source file\n"; std::terminate(); } if(auto error = action.Execute()) { llvm::errs() << "Failed to execute action: " << error << "\n"; std::terminate(); } auto tu = instance->getASTContext().getTranslationUnitDecl(); // tu->dump(); // ASTVistor visitor{instance->getPreprocessor(), buffer, instance->getASTContext(), // instance->getSema()}; visitor.TraverseDecl(tu); action.EndSourceFile(); };