【问题标题】:How to get AST only of main function using clang如何使用clang仅获取主要功能的AST
【发布时间】:2020-03-22 00:39:19
【问题描述】:

我想在源文件中获取 main 函数的 AST(假设有一个)来构建控制流图。我在这里找到了生成和遍历 AST 的代码:https://shaharmike.com/cpp/libclang/。 但问题是它进入了所有包含的文件。我也找到了这个话题:Clang AST visitor, avoid traversing include files。但似乎在 clang10 中进行了一些更改,建议的解决方案现在不起作用。或者也许还有其他方法可以获取用于构建控制流图的 AST?唯一的要求 - 它必须工作 C++ 源代码。

【问题讨论】:

  • 进入包含的文件是必要的,因为宏不是最终 AST 的一部分。除非你想要预处理器 AST?你到底想达到什么目的?
  • 我想为 C++ 代码构建控制流图。但是,由于我研究中的任务本身,我不能以任何方式使用已经实现的 CFG 构建器(clang 已经有一个)。所以,我认为正确的方法是获取 AST 的一部分,其中包含有关写入内容以及在源文件中写入的行的信息。而且由于大学本身的任务,最终目标不是创建可以涵盖任何内容的CFG builder,而是创建一个可以为简单程序创建CFG并掌握如何完成的程序。

标签: c++ clang abstract-syntax-tree control-flow-graph


【解决方案1】:

阅读the documentation 告诉我clang_visitChildren 只有在您返回CXChildVisit_Recurse 时才会“进入”它所指向的内容。所以你的访问函数应该检查游标类型并返回CXChildVisit_Continue,直到它到达名称等于main的函数定义。 main 的作用取决于你,但我建议返回 CXChildVisit_Break

【讨论】:

    【解决方案2】:

    所以,感谢 Botje 和这篇文章 (https://www.phototalks.idv.tw/academic/?p=1932) 我找到了解决方案。无论如何都不是最好的代码,但它可以工作。我希望它会帮助其他人。

    #include <iostream>
    #include <clang-c/Index.h>
    #include <string.h>
    using namespace std;
    
    ostream& operator<<(ostream& stream, const CXString& str)
    {
      stream << clang_getCString(str);
      clang_disposeString(str);
      return stream;
    }
    
    std::string getCursorKindName( CXCursorKind cursorKind )
    {
      CXString kindName  = clang_getCursorKindSpelling( cursorKind );
      std::string result = clang_getCString( kindName );
    
      clang_disposeString( kindName );
      return result;
    }
    
    std::string getCursorSpelling( CXCursor cursor )
    {
      CXString cursorSpelling = clang_getCursorSpelling( cursor );
      std::string result      = clang_getCString( cursorSpelling );
    
      clang_disposeString( cursorSpelling );
      return result;
    }
    CXChildVisitResult visitor1( CXCursor cursor, CXCursor /* parent */, CXClientData clientData )
    {
      CXSourceLocation location = clang_getCursorLocation( cursor );
        unsigned int locationstring =0;
         clang_getSpellingLocation  (   location, NULL, &locationstring, NULL,NULL);
      if( clang_Location_isFromMainFile( location ) == 0 )
        return CXChildVisit_Continue;
      CXCursorKind kind = clang_getCursorKind(cursor);
        std::string str2 ("main");
      CXCursorKind cursorKind = clang_getCursorKind( cursor );
      unsigned int curLevel  = *( reinterpret_cast<unsigned int*>( clientData ) );
      unsigned int nextLevel = curLevel + 1;
        std::cout << std::string( curLevel, '-' ) << " " << getCursorKindName(
        cursorKind ) << " (" << getCursorSpelling( cursor ) << ") ";
        std::cout << locationstring ;
        std::cout << endl;
    
        clang_visitChildren( cursor,
                             visitor1,
                             &nextLevel );
        return CXChildVisit_Continue;
    
    }
    
    CXChildVisitResult visitor( CXCursor cursor, CXCursor /* parent */, CXClientData clientData )
    {
      CXSourceLocation location = clang_getCursorLocation( cursor );
      if( clang_Location_isFromMainFile( location ) == 0 )
        return CXChildVisit_Continue;
      CXCursorKind kind = clang_getCursorKind(cursor);
        std::string str2 ("main");
      CXCursorKind cursorKind = clang_getCursorKind( cursor );
    
      unsigned int curLevel  = *( reinterpret_cast<unsigned int*>( clientData ) );
      unsigned int nextLevel = curLevel + 1;
      if (!((str2.compare(getCursorSpelling(cursor)))))
      {
        std::cout << std::string( curLevel, '-' ) << " " << getCursorKindName(
        cursorKind ) << " (" << getCursorSpelling( cursor ) << ")\n";
    
        clang_visitChildren( cursor,
                             visitor1,
                             &nextLevel );
        return CXChildVisit_Continue;
      }
      else
      {
      return CXChildVisit_Continue;
      }
    }
    
    int main()
    {
      CXIndex index = clang_createIndex(0, 0);
      CXTranslationUnit unit = clang_parseTranslationUnit(
         index,
         <source_file_name>, nullptr, 0,
        nullptr, 0,
         CXTranslationUnit_None);
          CXCursor cursor = clang_getTranslationUnitCursor(unit);
          unsigned int treeLevel = 0;
          clang_visitChildren( cursor, visitor, &treeLevel );
      clang_disposeTranslationUnit(unit);
      clang_disposeIndex(index);
    }
    

    【讨论】:

      猜你喜欢
      • 2020-03-21
      • 1970-01-01
      • 2011-07-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多