Проверка обобщенных атрибутов с помощью libclang

Я хотел бы проанализировать обобщенные атрибуты функций-членов класса в следующем примере:

class Foo
{
public:
void foo [[interesting]] ();
void bar ();
};

Используя libclang C API, я бы хотел различать foo а также bar (и знаю, что foo имеет interesting атрибут) в источнике. Это возможно? Мне трудно найти примеры или документацию, которая объясняет концепции, используемые в API (я нашел ссылку, но это сложно использовать, когда концепции не объяснены).

7

Решение

Что-то вроде следующего first_attr функция извлекает курсор первого атрибута переданного курсора, если он существует, или нулевой курсор, если его нет (непроверенный код … предупреждающий лектор)

CXChildVisitResult attr_visit(CXCursor cursor, CXCursor parent, CXClientData data) {
if (clang_isAttribute(cursor)) {
*data = cursor;
return CXChildVisit_Break;
}
return CXChildVisit_Continue;
}

CXCursor first_attr(const CXCursor& c) {
CXCursor attr;
unsigned visit_result = clang_visitChildren(c, attr_visit, &attr);
if (!visit_result) // attribute not found
attr = clang_getNullCursor();
return attr;
}

Что касается нахождения какого конкретного атрибута курсора a представляет собой результат clang_getCursorKind(a) может помочь, но доступны только следующие атрибуты:

CXCursor_IBActionAttr
CXCursor_IBOutletAttr
CXCursor_IBOutletCollectionAttr
CXCursor_CXXFinalAttr
CXCursor_CXXOverrideAttr
CXCursor_AnnotateAttr
CXCursor_AsmLabelAttr

Все остальное будет CXCursor_UnexposedAttr и единственный способ, которым я могу придумать, чтобы получить текст этого, состоит в том, чтобы изучить clang_getCursorExtent(a) (то есть прочитайте исходный код; ср. clang_tokenize). В случае аннотаций конкретная аннотация используется через clang_getCursorDisplayName,

2

Другие решения

Хотя мне не удалось найти обобщенные атрибуты в AST (кажется, они отбрасываются, когда или до создания AST, а не после него), я нашел обходной путь.

Есть annotate атрибут clang в следующей форме:

__attribute__((annotate("something")))

С помощью макроса я мог получить разумный синтаксис и аннотацию, которая видна в AST:

#define INTERESTING __attribute__((annotate("interesting")))

class Foo
{
public:
INTERESTING void foo();
void bar();
};

Атрибут будет дочерним по отношению к узлу метода, а его display_name будет строкой аннотации. Возможный дамп AST:

 <CursorKind.TRANSLATION_UNIT>
"test.h"{
__builtin_va_list <CursorKind.TYPEDEF_DECL>
"__builtin_va_list"type_info <CursorKind.CLASS_DECL>
"type_info"Foo <CursorKind.CLASS_DECL>
"Foo"{
<CursorKind.CXX_ACCESS_SPEC_DECL>
""foo <CursorKind.CXX_METHOD>
"foo()"{
<CursorKind.ANNOTATE_ATTR>
"interesting"}
bar <CursorKind.CXX_METHOD>
"bar()"}
}

Это дает тот же результат с void foo INTERESTING (); тоже.

2

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector