如果语句包含宏,则clang无法替换该语句 我使用CLAN尝试和C++ C++解析一些C++文件,并使所有的断片对都使用特定的样式。
示例:如果语句包含宏,则clang无法替换该语句 我使用CLAN尝试和C++ C++解析一些C++文件,并使所有的断片对都使用特定的样式。,c++,clang,clang++,C++,Clang,Clang++,示例: **Original** switch(...) { case 1: { <code> }break; case 2: { <code> break; } } **After replacement** switch(...) { case 1: { <code> break; } case 2: { &l
**Original**
switch(...)
{
case 1:
{
<code>
}break;
case 2:
{
<code>
break;
}
}
**After replacement**
switch(...)
{
case 1:
{
<code>
break;
}
case 2:
{
<code>
break;
}
}
到目前为止,如果代码部分不包含任何宏,我所拥有的正是我想要的。
我的问题是:clang是否以不同的方式对待扩展宏(如果我转储有问题的语句,它将显示扩展版本)?如果是这样的话,我怎样才能让它工作呢
其他可能有帮助的信息:
我使用新创建的CompoundStmt替换每个案例的子语句,我注意到ReplaceStmt如果“from”参数包含宏,则返回true,而方法返回true的唯一方式是
(from->())
返回-1您的问题是由的设计引起的 文章如下:
使用clang的SourceLocation进行宏扩展 设计灵活,可同时处理未展开位置和宏展开位置 如果令牌是扩展的结果,则需要考虑两个不同的位置:拼写位置(对应于令牌的字符位置)和实例化位置(使用令牌的位置-宏实例化点) 让我们以以下简单的源文件为例:
#define MACROTEST bool
int main() {
int var = 2;
switch(var)
{
case 1:
{
MACROTEST newvar;
}break;
case 2:
{
MACROTEST newvar;
break;
}
}
return 0;
}
假设我们要替换这两个声明
MACROTEST newvar;
与声明一起
int var = 2;
为了得到这样的东西
#define MACROTEST bool
int main() {
int var = 2;
switch(var)
{
case 1:
{
int var = 2;
}break;
case 2:
{
int var = 2;
break;
}
}
return 0;
}
如果我们输出AST(-AST dump),我们会得到以下结果(我包括一个图像,因为它比未着色的文本更直观):
正如您所看到的,我们感兴趣的第一个DeclStmt
报告的位置从第1行到第10行:这意味着clang在转储中报告从宏的行到使用宏的点的间隔:
#define MACROTEST [from_here]bool
int main() {
int var = 2;
switch(var)
{
case 1:
{
MACROTEST newvar[to_here];
}break;
case 2:
{
MACROTEST newvar;
break;
}
}
return 0;
}
(请注意,由于我的文本编辑器使用制表符,字符数可能与普通空格不同)
最终,这将触发Rewriter::getRangeSize
失败(-1
)和随后的true
返回值(这意味着失败-请参阅文档)
发生的情况如下:您收到了两个标记,其中第一个是宏ID(将返回true),而后者不是
为了成功地获得宏扩展语句的范围,我们需要后退一步,并与作为所有拼写位置和实例化位置的查询网关(如果您不记得这些术语,请后退一步)的需要进行通信。我无法比提供的详细描述更清楚:
可以查询SourceManager以获取有关SourceLocation的信息
对象,将它们转换为拼写或扩展位置。
拼写位置表示与令牌对应的字节的位置
来自和扩展位置表示位置所在的位置
用户的视图。例如,在宏展开的情况下
拼写位置指示扩展标记的来源和
展开位置指定展开位置
此时,您应该了解我首先解释所有这些内容的原因:如果您打算使用源范围进行替换,则需要使用适当的扩展间隔
回到我提出的示例,这是实现它的代码:
SourceLocation startLoc = declaration_statement->getLocStart();
SourceLocation endLoc = declaration_statement->getLocEnd();
if( startLoc.isMacroID() ) {
// Get the start/end expansion locations
std::pair< SourceLocation, SourceLocation > expansionRange =
rewriter.getSourceMgr().getImmediateExpansionRange( startLoc );
// We're just interested in the start location
startLoc = expansionRange.first;
}
if( endLoc.isMacroID() ) {
// will not be executed
}
SourceRange expandedLoc( startLoc, endLoc );
bool failure = rewriter.ReplaceText( expandedLoc,
replacer_statement->getSourceRange() );
if( !failure )
std::cout << "This will get printed if you did it correctly!";
而replacer\u语句
是用于替换的语句
int var = 2;
以上代码将为您提供以下信息:
#define MACROTEST bool
int main() {
int var = 2;
switch(var)
{
case 1:
{
int var = 2;
}break;
case 2:
{
int var = 2;
break;
}
}
return 0;
}
i、 e.宏扩展语句的完整和成功替换
参考资料:
- 强氧剂
- 叮当声源代码
SourceLocation startLoc = rewriter.getSourceMgr().getFileLoc(
declaration_statement->getLocStart());
SourceLocation endLoc = rewriter.getSourceMgr().getFileLoc(
declaration_statement->getLocEnd());
此API函数与Marco在其代码中编写的函数相同,但会自动执行
如果我们看一下函数的实现getFileLoc():
以下是该功能的说明:
给定Loc,如果是宏位置,则返回扩展位置或拼写位置,具体取决于它是否来自宏参数
SourceLocation startLoc = rewriter.getSourceMgr().getFileLoc(
declaration_statement->getLocStart());
SourceLocation endLoc = rewriter.getSourceMgr().getFileLoc(
declaration_statement->getLocEnd());
SourceLocation getFileLoc(SourceLocation Loc) const {
if (Loc.isFileID()) return Loc;
return getFileLocSlowCase(Loc);
}
SourceLocation SourceManager::getFileLocSlowCase(SourceLocation Loc) const {
do {
if (isMacroArgExpansion(Loc))
Loc = getImmediateSpellingLoc(Loc);
else
Loc = getImmediateExpansionRange(Loc).first;
} while (!Loc.isFileID());
return Loc;
}