在 Clang 中对字符串进行漂亮的打印语句

Pretty Print Statement to String in Clang

我正在尝试将 Clang 语句漂亮地打印到 string 以便打印语句的 C/C++ 代码。我通过以下方式执行此操作:

//Generate string and string ostream.
string stmt;
raw_string_ostream stream(stmt);

//Get statement from ASTMatcher and print to ostream.
auto* statement = result.Nodes.getNodeAs<clang::Expr>(types[VAR_STMT]);
statement->printPretty(stream, NULL, PrintingPolicy(LangOptions()));

//Flush ostream buffer.
stream.flush();
cout << statement << endl;


此代码编译并且 运行 没问题。但是,当我 运行 以下代码时,我得到 statement 对象的地址打印到 string。例如,当我 运行 这段代码时,我得到以下输出:

0x3ccd598
0x3ccd5b0
0x3ccd728
0x3ccdc88
0x3ccdd08


Clang 的文档中关于 printPretty(...) 的文档并不多,那么 正确的 打印 [=14= 代码的方法是什么? ] 到一个字符串?

我在尝试让它工作时发现的一个解决方案来自 2013 年的 Clang developers post

而不是:

//Generate string and string ostream.
string stmt;
raw_string_ostream stream(stmt);

//Get statement from ASTMatcher and print to ostream.
auto* statement = result.Nodes.getNodeAs<clang::Expr>(types[VAR_STMT]);
statement->printPretty(stream, NULL, PrintingPolicy(LangOptions()));

//Flush ostream buffer.
stream.flush();
cout << statement << endl;

我现在的代码是:

//Get the statement from the ASTMatcher
auto *statement = result.Nodes.getNodeAs<clang::Expr>(types[VAR_STMT]);

//Get the source range and manager.
SourceRange range = statement->getSourceRange();
const SourceManager *SM = result.SourceManager;

//Use LLVM's lexer to get source text.
llvm::StringRef ref = Lexer::getSourceText(CharSourceRange::getCharRange(range), *SM, LangOptions());
cout << ref.str() << endl;

虽然我不太确定任何潜在的缺点,但这种方法似乎确实有效。

您似乎因为相似的变量名称而感到困惑。您有一个 string 类型的变量 stmt,并且您有一个(大概)clang::Stmt * 类型的变量 statementprintPretty 调用正在修改 stream 变量,该变量写入 stmt,而不是 statement。然后打印 statement,指向 clang 类型的指针。所以很自然地,对指针类型的 cout 调用会写入指针的地址。

将您的 cout 行更改为写出 stmt,您将得到您期望的结果。

我刚刚发现可以使用 raw_string_ostream:

将语句打印到字符串中
// stmt is the statement you wish to print
string stmtToString(Stmt *stmt){
    clang::LangOptions lo;
    string out_str;
    llvm::raw_string_ostream outstream(out_str);
    stmt->printPretty(outstream, NULL, PrintingPolicy(lo));
    return out_str;
}