Twój problem jest spowodowany przez konstrukcję SourceLocation.
Wyrób następująco:
makr ze szczęk jest SourceLocation
SourceLocation
ma być wystarczająco elastyczna, aby obsługiwać zarówno nieporowate położenia i makro rozszerzone położenie jednocześnie.
Jeżeli znacznik jest wynikiem rozszerzania, to istnieją dwa różne miejsca być utrzymywane pod uwagę: położenie pisowni (lokalizacja znaków odpowiadających tokena) i położenie tworzenia instancji (The lokalizacja, w której użyto tokena - punkt inicjowania makr).
Weźmy następujący prosty plik źródłowy jako przykład:
#define MACROTEST bool
int main() {
int var = 2;
switch(var)
{
case 1:
{
MACROTEST newvar;
}break;
case 2:
{
MACROTEST newvar;
break;
}
}
return 0;
}
i przypuśćmy, że chcemy wymienić dwie deklaracje sprawozdania
MACROTEST newvar;
ze stwierdzeniem deklaracji
int var = 2;
aby uzyskać coś takiego,
#define MACROTEST bool
int main() {
int var = 2;
switch(var)
{
case 1:
{
int var = 2;
}break;
case 2:
{
int var = 2;
break;
}
}
return 0;
}
jeśli wyjście AST (-ast-dump) otrzymujemy następujące (jestem w tym obrazie, ponieważ jest to bardziej intuicyjne niż tekst tylko Niepokolorowany):
jako możesz zobaczyć lokalizację zgłoszoną dla pierwszego DeclStmt
, które nas interesuje, obejmuje zakres od 1 do 10: oznacza to, że klang zgłasza w zrzucie przedział rozciągający się od linii makra do punktu, w którym makro jest używane:
#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;
}
(zauważyć, że liczba znaków nie może być taka sama, z przestrzeni normalnych, ponieważ mój edytor tekstu używanych zakładek)
Ostatecznie to wyzwalających awarię Rewriter::getRangeSize
(-1
), oraz kolejne Rewriter::ReplaceStmt
wartość true
zwrotny (co oznacza awarię - patrz dokumentacja).
To, co się dzieje, jest następujące: otrzymujesz kilka znaczników SourceLocation
, gdzie pierwszym jest identyfikator makra (isMacroID()
zwróci wartość true), podczas gdy drugie nie.
aby skutecznie pozbyć zakresu rachunku makro rozszerzone musimy zrobić krok do tyłu i komunikować się z SourceManager
który jest kwerenda Bramka dla wszystkich lokalizacjach pisowni i miejscach instancji (potrwać cofnij, jeśli nie pamiętasz tych terminów) potrzeb. Nie mogę być bardziej jasne niż szczegółowym opisem zawartym in the documentation:
SourceManager można przeszukiwać informacje na temat SourceLocation obiektów, zamieniając je w zarówno ortograficzne lub rozszerzeń lokalizacji. Miejsca sprawdzania pisowni reprezentują miejsce, w którym przybył bajt odpowiadający tokenowi , a lokalizacje rozszerzeń reprezentują położenie użytkownika w widoku . Na przykład w przypadku rozszerzenia makra, lokalizacja pisowni wskazuje, skąd pochodzi rozszerzony token, a lokalizacja rozwinięcia określa, gdzie została rozwinięta.
W tym momencie powinno być coraz dlaczego wyjaśniłem wszystkie te rzeczy w pierwszej kolejności: jeśli masz zamiar używać zakresów źródłowych do zastąpienia, trzeba użyć odpowiedniego odstępu ekspansji.
Powrót do próbki zaproponowałem, jest to kod, aby osiągnąć go:
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
jest jedno z dwóch
MACROTEST newvar;
podczas replacer_statement
jest stwierdzenie wykorzystane do zastąpienia
int var = 2;
Powyższy kod zapewnia:
#define MACROTEST bool
int main() {
int var = 2;
switch(var)
{
case 1:
{
int var = 2;
}break;
case 2:
{
int var = 2;
break;
}
}
return 0;
}
tj. Pełne i pomyślne zastąpienie makro-rozwiniętego wyciągu.
Referencje: