2013-10-29 16 views
7

Ich würde verallgemeinern Attribute der Klasse Elementfunktionen in dem folgende Beispiel analysieren mag:Inspizieren generali Attribute mit libclang

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

Mit dem libclang C-API, würde ich gerne zwischen foo und bar (und weiß unterscheiden, dass foo hat das interesting Attribut) in der Quelle. Ist das möglich? Es fällt mir schwer, Beispiele oder Dokumentationen zu finden, die die in der API verwendeten Konzepte erklären (ich habe eine Referenz gefunden, aber diese ist schwer zu verwenden, wenn die Konzepte nicht erklärt werden).

Antwort

1

Während ich die generalisierten Attribute in der AST nicht finden konnte (es scheint, dass sie vor oder nach der Erstellung der AST gelöscht wurden, nicht danach), fand ich eine Umgehungslösung.

Es gibt ein annotate Klirren Attribut in der folgenden Form:

__attribute__((annotate("something"))) 

Mit einem Makro ich eine angemessene Syntax und eine Anmerkung bekommen konnte, die in dem AST sichtbar ist:

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

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

Das Attribut ist das Kind des Methodenknotens, wobei display_name die Anmerkungszeichenfolge ist. Ein möglicher 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()" 
    } 
} 

Es produziert die gleiche Leistung mit void foo INTERESTING(); auch.

2

So etwas wie die folgende first_attr Funktion wird der Cursor des ersten Attributs des übergebenen Cursor holen, wenn es vorhanden ist, oder ein Null-Cursor, wenn dies nicht der Fall (ungetestet Code ... Vorbehalt Lektor)

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

Bezüglich Feststellung, die spezifisch einen Cursor-Attribut a darstellt, kann das Ergebnis der clang_getCursorKind(a) helfen, aber die einzigen ausgesetzt Attribute sind:

CXCursor_IBActionAttr 
CXCursor_IBOutletAttr 
CXCursor_IBOutletCollectionAttr 
CXCursor_CXXFinalAttr 
CXCursor_CXXOverrideAttr 
CXCursor_AnnotateAttr 
CXCursor_AsmLabelAttr 

Alles andere ein CXCursor_UnexposedAttr ein sein wird d die einzige Möglichkeit, die ich mir vorstellen kann, um den Text davon zu bekommen, ist zu untersuchen clang_getCursorExtent(a) (d. h., lesen Sie den Quellcode; vgl. clang_tokenize). Im Fall von Anmerkungen ist die verwendete spezifische Anmerkung unter clang_getCursorDisplayName verfügbar.

+0

Ich versuchte dies mit den Python-Bindungen, um den Code zu prototypieren, aber das Attribut war im AST überhaupt nicht sichtbar (nicht als unexponiertes Attribut). Ein "noreturn" -Attribut erschien in meinem AST-Dump, als ich es hinzufügte. –