Я создаю инструмент для преобразования исходного кода с помощью clang. Что я хочу сделать, так это сохранить инструменты, сделанные с помощью двоичного оператора =. В настоящее время у меня возникают проблемы с переписыванием выражений, содержащих вызовы макросов. Я немного покопался и нашел некоторую информацию, которая помогла мне понять (например, clang не может заменить оператор, если он содержит макрос). Но я до сих пор не знаю, как решить эту проблему.
Конкретно, предположим, что у вас есть:
#define a(x) ((x) * 10 + 1)
class my_class {
int x;
public:
int my_function() {
x = a(0);
return x;
}
};
Я хочу переписать это примерно так:
#ifndef _instrument_noclash
#define _instrument_noclash(name, expr, instance_no) \
(*({ \
typeof(expr) *_t_instrument_no_clash##instance_no = &(expr); \
_t_instrument_no_clash##instance_no; \
}))
#endif
#define a(x) ((x) * 10 + 1)
class my_class {
int x;
public:
int my_function() {
_instrument_noclash("x",(this->x=((0) * 10 + 1)),0);
return x;
}
};
Проблема (для меня) проста: как мне определить физическое расположение окончания выражения справа от знака = оператора? Без этих знаний я в конечном итоге перезаписываю конец выражения заявление. Сканируя API, кажется, что нет простого способа сделать это. Я пробовал несколько способов получить конечное исходное местоположение:
op->getEndLoc()
, гдеop
— экземплярBinaryOperator
. Это не работает, потому что конечное местоположение в AST не совпадает с физическим конечным местоположением выражения из-за раскрытия макроса.sm.getSpellingLoc(op->getEndLoc())
, гдеsm
— менеджер исходного кода. Это просто возвращаетop->getEndLoc()
.sm.getExpansionLoc(op->getEndLoc())
. Это близко, но возвращаемое местоположение является концом имени макроса, поэтому аргументы макроса не удаляются.
Любые предложения (или более простой способ достижения той же цели) приветствуются.