在 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 *
类型的变量 statement
。 printPretty
调用正在修改 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;
}
我正在尝试将 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 *
类型的变量 statement
。 printPretty
调用正在修改 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;
}