2012-06-18 11 views
13

Dado un objeto AST en clang, ¿cómo puedo obtener el código detrás de él? He intentado editar el código en el tutorial, y añadió:Obteniendo la fuente detrás de clang's AST

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

pero por desgracia, no se imprime toda la declaración typedef, sólo la mitad de ella! El mismo fenómeno ocurrió al imprimir Expr.

¿Cómo puedo imprimir y ver toda la cadena original que constituye la declaración?

+0

Creo que la ubicación de la fuente final apunta al último token en el rango (no uno más allá del final) y por lo tanto se perderá el último token. – bames53

+0

@ bames53 parece que estás en lo cierto! ¿Cómo obtengo este último token? – mikebloch

+0

Aparte del hecho de que probablemente debería ser '_e' no' _w' en la tercera línea, ¿no es la diferencia en la última línea al revés? (Es decir, 'e - b' no' b - e') –

Respuesta

14

utilizar el módulo Lexer:

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

Esa es una muy buena respuesta, pero cuando trato de imprimir un párrafo, comento '/ ** ... * /' usando esta función 'std :: string fullComment2str (comments :: FullComment * comment, clang :: SourceManager * sm, clang :: LangOptions lopt) { if (! comment) { return std :: string(); } clang :: SourceLocation b (comment-> getLocStart()), _e (comment-> getLocEnd()); clang :: SourceLocation e (clang :: Lexer :: getLocForEndOfToken (_e, 0, * sm, lopt)); return std :: string (sm-> getCharacterData (b), sm-> getCharacterData (e) -sm-> getCharacterData (b)); } ' La salida no contiene marcadores de inicio y finalización. –

+1

Tenga cuidado, hice algunas pruebas con este enfoque y, a veces, para cantidades extremadamente grandes de código, los resultados de 'getCharacterData()' no producen punteros del mismo buffer ... He tenido el puntero "final" aterriza en la pila mientras el puntero de "inicio" apunta hacia algún lugar en el montón ... Esto lleva a que la herramienta se cuelgue o inunde su terminal con la memoria basura. –

+0

@StevenLu ¿Entiendes lo que está mal con los métodos? ¿Cómo puedo arreglarlo? –

5

El siguiente código funciona para mí.

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

El método de Elazar funcionó para mí, excepto cuando se trataba de una macro. La siguiente corrección lo resolvió:

std::string decl2str(clang::Decl *d) { 
    clang::SourceLocation b(d->getLocStart()), _e(d->getLocEnd()); 
    if (b.isMacroID()) 
     b = sm->getSpellingLoc(b); 
    if (e.isMacroID()) 
     e = sm->getSpellingLoc(e); 
    clang::SourceLocation e(clang::Lexer::getLocForEndOfToken(_e, 0, *sm, lopt)); 
    return std::string(sm->getCharacterData(b), 
     sm->getCharacterData(e)-sm->getCharacterData(b)); 
} 
Cuestiones relacionadas