我想在源文件中获取 main 函数的 AST(假设有一个)来构建控制流图。我在这里找到了生成和遍历 AST 的代码: https ://shaharmike.com/cpp/libclang/ 。但问题是它进入了所有包含的文件。我还找到了这个主题:Clang AST visitor, Avoid traversing include files。但似乎在 clang10 中进行了一些更改,建议的解决方案现在不起作用。或者也许还有其他方法可以获取 AST 来构建控制流图?唯一的要求 - 它必须工作 C++ 源代码。
问问题
521 次
2 回答
2
阅读文档告诉我,clang_visitChildren
只有在您返回时才会“进入”它所指向的任何内容CXChildVisit_Recurse
。因此,您的访问函数应该检查游标类型并返回CXChildVisit_Continue
,直到它到达名称为 equals 的函数定义main
。它的作用main
取决于你,但我建议返回CXChildVisit_Break
.
于 2019-11-26T15:28:19.110 回答
0
所以,感谢 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);
}
于 2019-11-26T20:32:07.897 回答