В заголовке вопросов запрашивается libclang
, но при использовании Lexer::getSourceText
я предполагаю, что это libTooling
.Остальная часть моего ответа жизнеспособна только с точки зрения libTooling
.
Решение 1
Lexer работает на уровне токенов. Запятая также является токеном, так что вы можете взять конечное местоположение параметра и получить следующий токен, используя Lexer :: findNextToken .
Вот это ParmVarDecl
(для параметров функции) и CallExpr
(для аргументов функции) посещают функции, которые показывают, как его использовать:
template <class T> void printNextTokenLocation(T *Node) {
auto NodeEndLocation = Node->getSourceRange().getEnd();
auto &SM = Context->getSourceManager();
auto &LO = Context->getLangOpts();
auto NextToken = Lexer::findNextToken(NodeEndLocation, SM, LO);
if (!NextToken) {
return;
}
auto NextTokenLocation = NextToken->getLocation();
llvm::errs() << NextTokenLocation.printToString(SM) << "\n";
}
bool VisitParmVarDecl(ParmVarDecl *Param) {
printNextTokenLocation(Param);
return true;
}
bool VisitCallExpr(CallExpr *Call) {
for (auto *Arg : Call->arguments()) {
printNextTokenLocation(Arg);
}
return true;
}
Для следующего фрагмента кода:
#define FOO(x) int x
#define BAR float d
#define MINUS -
#define BLANK
void foo(int a, double b ,
FOO(c) , BAR) {}
int main() {
foo( 42 ,
36.6 , MINUS 10 , BLANK 0.0 );
return 0;
}
создаетследующий вывод (шесть мест для запятых и два для круглых скобок):
test.cpp:6:15
test.cpp:6:30
test.cpp:7:19
test.cpp:7:24
test.cpp:10:17
test.cpp:11:12
test.cpp:11:28
test.cpp:11:43
Это довольно низкоуровневый и подверженный ошибкам подход.Тем не менее, вы можете изменить способ решения исходной проблемы.
Решение 2
Clang хранит информацию о расширенных макросах в своих исходных местоположениях.Вы можете найти соответствующие методы в SourceManager
(например, isMacroArgExpansion или isMacroBodyExpansion ).В результате вы можете посещать ParmVarDecl
узлы и проверять их расположение на предмет расширения макросов.
Я бы настоятельно рекомендовал двигаться во втором направлении.
Я надеюсь, что эта информация будет полезна.Удачного взлома с Clang!
UPD если говорить об атрибутах, к сожалению, у вас не будет большого выбора.Clang игнорирует любой неизвестный атрибут, и это поведение не настраивается .Если вы не хотите исправлять сам Clang и добавлять свои атрибуты в Attrs.td , тогда вы действительно ограничены токенами и первым подходом.