zoukankan      html  css  js  c++  java
  • Clang教程之实现源源变化(3)

    一个高级的源源变换,主要是为了展示如何进行AST Declaration的遍历和代码的规整化处理,可以将其作为一个代码自动规整化工具进行使用

    实现代码如下:

      1 //------------------------------------------------------------------------------
      2 // Simple Rewrtie Sample 
      3 //
      4 //
      5 // jourluohua (jourluohua@gmail.com)
      6 // This code is in the public domain
      7 //------------------------------------------------------------------------------
      8 #include <sstream>
      9 #include <string>
     10 #include <fstream>
     11 
     12 #include "clang/AST/AST.h"
     13 #include "clang/AST/ASTConsumer.h"
     14 #include "clang/AST/RecursiveASTVisitor.h"
     15 #include "clang/Frontend/ASTConsumers.h"
     16 #include "clang/Frontend/CompilerInstance.h"
     17 #include "clang/Frontend/FrontendActions.h"
     18 #include "clang/Rewrite/Core/Rewriter.h"
     19 #include "clang/Tooling/CommonOptionsParser.h"
     20 #include "clang/Tooling/Tooling.h"
     21 #include "llvm/Support/raw_ostream.h"
     22 
     23 using namespace clang;
     24 using namespace clang::driver;
     25 using namespace clang::tooling;
     26 
     27 static llvm::cl::OptionCategory ToolingSampleCategory("Simple Rewriter");
     28 
     29 // Implementation of the ASTConsumer interface for reading an AST produced
     30 // by the Clang parser.
     31 class MyASTConsumer : public ASTConsumer {
     32 private:
     33     std::string InFile;
     34     SourceManager *SM;
     35     Rewriter TheRewriter;
     36     
     37   public:
     38     MyASTConsumer(SourceManager* sm, StringRef _InFile, Rewriter& theRew)
     39         : SM(sm), InFile(_InFile), TheRewriter(theRew){}
     40 
     41     void HandleTranslationUnit(ASTContext &Context) override;
     42 
     43     StringRef getInFile() { return InFile; }
     44 };
     45 void MyASTConsumer::HandleTranslationUnit(ASTContext &Context){
     46   DeclContext::decl_iterator D = Context.getTranslationUnitDecl()->decls_begin();
     47   DeclContext::decl_iterator DEnd = Context.getTranslationUnitDecl()->decls_end();
     48   PrintingPolicy Policy(Context.getLangOpts());
     49   while (D != DEnd)
     50   {
     51     SourceLocation Loc = SM->getExpansionLoc(D->getLocation());
     52     SourceLocation LocStart = D->getBeginLoc();
     53     SourceLocation LocEnd = D->getEndLoc();
     54     //(*D)->dump();
     55     if (Loc.isInvalid() || !SM->isWrittenInMainFile(Loc) || D->isImplicit() ||
     56         LocStart.isInvalid()) {
     57       ++D;
     58       continue;
     59     }
     60 
     61     std::string prettyBufS;
     62     llvm::raw_string_ostream prettyBuf(prettyBufS);
     63     D->print(prettyBuf, Policy);
     64 
     65     if (LocEnd.isInvalid()) {
     66       TheRewriter.InsertTextAfter(LocStart, "
    " + prettyBuf.str());
     67       ++D;
     68       continue;
     69     }
     70 
     71     const char *startBuf = SM->getCharacterData(LocStart);
     72     const char *endBuf = SM->getCharacterData(LocEnd);
     73 
     74     char separator;
     75     const char *separatorBuf;
     76 
     77     switch (D->getKind()) {
     78       case Decl::Function: {
     79         FunctionDecl *FD = cast<FunctionDecl>(*D);
     80 
     81         if (!FD->isThisDeclarationADefinition()) {
     82           separator = ';';
     83           separatorBuf = strchr(endBuf, separator);
     84           TheRewriter.ReplaceText(LocStart, separatorBuf - startBuf, prettyBuf.str());
     85         }
     86         else {
     87           separator = '}';
     88           separatorBuf = strchr(endBuf, separator);
     89           TheRewriter.ReplaceText(LocStart, separatorBuf - startBuf + 1, prettyBuf.str());
     90         }
     91         ++D;
     92         break;
     93       }
     94       case Decl::Var: {
     95         ++D;
     96         bool flag = true;
     97         while (D != DEnd && flag == true) {
     98           flag = false;
     99           if (VarDecl *VD = dyn_cast<VarDecl>(*D)) {
    100             if (VD->getBeginLoc() == LocStart) {
    101               prettyBuf << "; ";
    102               VD->print(prettyBuf, Policy);
    103               ++D;
    104               flag = true;
    105             }
    106           }
    107         }
    108 
    109         separator = ';';
    110         separatorBuf = strchr(endBuf, separator);
    111         TheRewriter.ReplaceText(LocStart, separatorBuf - startBuf, prettyBuf.str());
    112         break;
    113       }
    114       case Decl::TypeAlias:
    115       case Decl::Typedef: {
    116         separator = ';';
    117         separatorBuf = strchr(endBuf, separator);
    118         TheRewriter.ReplaceText(LocStart, separatorBuf - startBuf, prettyBuf.str());
    119         ++D;
    120         break;
    121       }
    122       case Decl::Record: {
    123         ++D;
    124         if (D != DEnd) {
    125           SourceLocation NextLocStart = D->getBeginLoc();
    126           SourceLocation NextLocEnd = D->getEndLoc();
    127           // Handle the following case:
    128           // typedef struct abc {
    129           //   ...;
    130           // } abc;
    131           if (NextLocStart.isValid() && NextLocStart < LocStart) {
    132             prettyBuf << ";
    ";
    133             D->print(prettyBuf, Policy);
    134             startBuf = SM->getCharacterData(NextLocStart);
    135             endBuf = SM->getCharacterData(NextLocEnd);
    136             LocStart = NextLocStart;
    137             ++D;
    138           }
    139         }
    140 
    141         separator = ';';
    142         separatorBuf = strchr(endBuf, separator);
    143         TheRewriter.ReplaceText(LocStart, separatorBuf - startBuf, prettyBuf.str());
    144         break;
    145       }
    146       
    147       default:
    148         llvm_unreachable("should handle the decl kind");
    149     }
    150   }
    151 
    152   const RewriteBuffer *RewriteBuf = TheRewriter.getRewriteBufferFor(SM->getMainFileID());
    153   
    154   //*OutFile << std::string(RewriteBuf->begin(), RewriteBuf->end()); 
    155   std::ofstream outEdF("dpu_test.cpp", std::ofstream::out);
    156 
    157   if(outEdF.good()){
    158       std::string tmp(RewriteBuf->begin(), RewriteBuf->end()); 
    159       outEdF << tmp;
    160       //std::cout << tmp;
    161   }
    162 
    163 
    164   outEdF.close();
    165 
    166 
    167 }
    168 // For each source file provided to the tool, a new FrontendAction is created.
    169 class MyFrontendAction : public ASTFrontendAction {
    170 public:
    171   MyFrontendAction() {}
    172 
    173 
    174   std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
    175                                                  StringRef inFile) override {
    176     llvm::errs() << "** Creating AST consumer for: " << inFile << "
    ";
    177     TheRewriter.setSourceMgr(CI.getSourceManager(), CI.getLangOpts());
    178     return std::make_unique<MyASTConsumer>(&(CI.getSourceManager()), inFile, TheRewriter);
    179   }
    180   Rewriter TheRewriter;
    181 };
    182 
    183 int main(int argc, const char **argv) {
    184   llvm::Expected<CommonOptionsParser> op=CommonOptionsParser::create(argc, argv, ToolingSampleCategory);
    185   
    186   ClangTool Tool(op.get().getCompilations(), op.get().getSourcePathList());
    187 
    188   // ClangTool::run accepts a FrontendActionFactory, which is then used to
    189   // create new objects implementing the FrontendAction interface. Here we use
    190   // the helper newFrontendActionFactory to create a default factory that will
    191   // return a new MyFrontendAction object every time.
    192   // To further customize this, we could create our own factory class.
    193   return Tool.run(newFrontendActionFactory<MyFrontendAction>().get());
    194 }
  • 相关阅读:
    kibana ,logstash and filebeat
    The Run-Time Constant Pool The Constant Pool
    hsdb
    The Dataflow Model: A Practical Approach to Balancing
    编译器
    汇编
    状态机
    lsm-tree
    Serviceability
    JIT编译器
  • 原文地址:https://www.cnblogs.com/jourluohua/p/14520336.html
Copyright © 2011-2022 走看看