2012-06-18 3 views
13

Gibt es ein AST-Objekt in clang, wie bekomme ich den Code dahinter? Ich habe versucht, den Code in den tutorial Bearbeitung und fügte hinzu:Ermitteln der Quelle hinter dem AST von CLAng

clang::SourceLocation _b = d->getLocStart(), _e = d->getLocEnd(); 
char *b = sourceManager->getCharacterData(_b), 
     e = sourceManager->getCharacterData(_E); 
llvm:errs() << std::string(b, e-b) << "\n"; 

aber leider hat es nicht die ganze typedef Erklärung drucken, nur etwa die Hälfte davon! Die gleichen Phänomene traten beim Drucken auf Expr auf.

Wie kann ich die gesamte ursprüngliche Zeichenfolge drucken und anzeigen, die die Deklaration darstellt?

+0

Ich denke, die Endquelle Position zeigt auf den letzten Token in der Reihe (nicht eine nach dem Ende) und so verpassen Sie das letzte Token. – bames53

+0

@ bames53 sieht aus wie du bist richtig! Wie bekomme ich dann dieses letzte Token? – mikebloch

+0

Abgesehen davon, dass es in der dritten Zeile wahrscheinlich "_e" nicht "_w" sein sollte, ist der Unterschied in der letzten Zeile nicht falsch? (I.e. 'e - b' nicht' b - e') –

Antwort

14

Verwenden Sie das Lexer Modul:

clang::SourceManager *sm; 
clang::LangOptions lopt; 

std::string decl2str(clang::Decl *d) { 
    clang::SourceLocation b(d->getLocStart()), _e(d->getLocEnd()); 
    clang::SourceLocation e(clang::Lexer::getLocForEndOfToken(_e, 0, *sm, lopt)); 
    return std::string(sm->getCharacterData(b), 
     sm->getCharacterData(e)-sm->getCharacterData(b)); 
} 
+1

Das ist eine wirklich gute Antwort, aber wenn ich versuche, einen Absatzkommentar '/ ** ... * /' mit dieser Funktion 'std :: string fullComment2str (Kommentar :: FullComment * Kommentar, clang :: SourceManager * sm, clang :: LangOptions lopt) { if (! Kommentar) { return std :: string(); } clang :: SourceLocation b (Kommentar-> getLocStart()), _e (Kommentar-> getLocEnd()); clang :: Quelllokation e (clang :: Lexer :: getLocForEndOfToken (_e, 0, * sm, lopt)); return std :: string (sm-> getCharacterData (b), sm-> getCharacterData (e) -sm-> getCharacterData (b)); } ' Die Ausgabe enthält keine Begin + End-Marker. –

+1

Seien Sie gewarnt, ich habe einige Tests mit diesem Ansatz, und manchmal für extrem große Mengen an Code, die Ergebnisse von 'getCharacterData()' nicht Char-Zeiger aus dem gleichen Puffer ... Ich hatte den "Ende" -Zeiger landen auf dem Stapel, während der "Begin" -Zeiger irgendwo auf den Heap zeigt ... Dies führt dazu, dass das Tool mit dem Müllspeicher kollidiert oder überflutet wird. –

+0

@StevenLu Hast du verstanden, was mit den Methoden nicht stimmt? Wie kann ich es reparieren? –

5

Der folgende Code funktioniert für mich.

std::string decl2str(clang::Decl *d, SourceManager &sm) { 
    // (T, U) => "T,," 
    string text = Lexer::getSourceText(CharSourceRange::getTokenRange(d->getSourceRange()), sm, LangOptions(), 0); 
    if (text.size() > 0 && (text.at(text.size()-1) == ',')) //the text can be "" 
     return Lexer::getSourceText(CharSourceRange::getCharRange(d->getSourceRange()), sm, LangOptions(), 0); 
    return text; 
} 
0

Elazars Methode funktionierte für mich, außer wenn ein Makro beteiligt war. Die folgende Korrektur löste es: