你的問題是由SourceLocation設計造成的。
的文章如下:
鏗鏘的SourceLocation
SourceLocation
宏擴展的設計具有足夠的靈活性來處理雙方未展開的位置與宏觀擴張地點在同一時間。
如果令牌是膨脹的結果,則存在要被保持到兩個不同的位置:在拼寫位置和實例化位置(對應於所述令牌的字符的位置)(在使用令牌的位置 - 宏實例化點)。
讓我們以下面這個簡單的源文件爲例:
#define MACROTEST bool
int main() {
int var = 2;
switch(var)
{
case 1:
{
MACROTEST newvar;
}break;
case 2:
{
MACROTEST newvar;
break;
}
}
return 0;
}
,並假設我們想聲明語句
int var = 2;
更換兩個聲明語句
MACROTEST newvar;
爲了得到像這樣的東西
#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轉儲),我們得到以下(我包括圖像,因爲它不僅僅是無色文字更直觀):
爲您可以看到我們感興趣的第一個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
)和後續Rewriter::ReplaceStmt
true
返回值(這意味着失敗 - 請參閱文檔)。
發生的情況如下:您正在收到一對SourceLocation
標記,其中第一個是宏ID(isMacroID()
將返回true),而後者不是。
爲了順利拿到我們需要後退一步,並與SourceManager
這是查詢網關爲所有拼寫地點和實例位置溝通的宏擴展語句的程度(取退一步,如果你不記得這些條款)的需要。我不能比提供in the documentation的詳細描述中更加清楚:
的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!";
的declaration_statement
是兩個
MACROTEST newvar;
一方而replacer_statement
是用於替換的聲明
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;
}
即宏擴展語句的完整和成功替代。
參考文獻: