Validating generic attributes with libclang

I would like to analyze the generalized attributes of class member functions in the following example:

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

Using the libclang C API, I would like to distinguish between foo and bar (and I know that foo has an interesting attribute) in the source. Is it possible? I find it difficult to find examples or documentation explaining the concepts used in the API (I found a link, but it is difficult to use when the concepts are not explained).

+7
c ++ clang abstract-syntax-tree libclang
source share
2 answers

So far, I have not been able to find generalized attributes in the AST (it seems that they are discarded during the construction of the AST, and not after it), I found a workaround.

There is an annotate clang attribute in the following form:

 __attribute__((annotate("something"))) 

With a macro, I can get a reasonable syntax and annotation that is visible in AST:

 #define INTERESTING __attribute__((annotate("interesting"))) class Foo { public: INTERESTING void foo(); void bar(); }; 

The attribute will be a child of the node method, with its instance_name being an annotation string. Possible AST dump:

  <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()" } } 

It produces the same output with void foo INTERESTING (); .

+1
source share

Something like the following first_attr function will retrieve the cursor of the first attribute of the passed cursor, if it exists, or the null cursor if it is not running (untested code ... caveat lector)

 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; } 

As for determining which particular attribute cursor a displays, the result of clang_getCursorKind(a) may help, but the only recognized attributes are:

 CXCursor_IBActionAttr CXCursor_IBOutletAttr CXCursor_IBOutletCollectionAttr CXCursor_CXXFinalAttr CXCursor_CXXOverrideAttr CXCursor_AnnotateAttr CXCursor_AsmLabelAttr 

Everything else will be CXCursor_UnexposedAttr , and the only way I can present its text is to study clang_getCursorExtent(a) (i.e. read the source code, cf. clang_tokenize ). For annotations, the specific annotation used is available through clang_getCursorDisplayName .

+2
source share

All Articles