2012-06-18 2 views
13

Учитывая объект AST в clang, как я могу получить код за ним? Я попытался редактирование коды в tutorial, и добавил:Получение источника позади 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"; 

, но увы, не печатал всю декларацию ЬурейеЙ, только около половины этого! То же самое произошло при печати Expr.

Как распечатать и увидеть всю исходную строку, составляющую декларацию?

+0

Я думаю, что местоположение конечного источника указывает на последний токен в диапазоне (не один за его конец), и поэтому вы пропустите последний токен. – bames53

+0

@ bames53 похоже, что вы правы! Как мне получить этот последний токен? – mikebloch

+0

Помимо того, что в третьей строке это, вероятно, должно быть '_e' not' _w', разве разница в последней строке неправильная? (I.e. 'e - b' not' b - e') –

ответ

14

Используйте 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

Это действительно хороший ответ, но когда я пытаюсь напечатать комментарий параграфа '/ ** ... * /', используя эту функцию 'std :: string fullComment2str (комментарии :: FullComment * комментарий, 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)); } ' Выход не содержит маркеров начала + конца. –

+1

Будьте осторожны, я сделал некоторые тесты с этим подходом, а иногда и для чрезвычайно больших количеств кода, результаты 'getCharacterData()' не дают указателей на символы из того же буфера ... У меня был указатель «end» приземляйтесь в стек, в то время как указатель «begin» указывает где-то в куче ... Это приводит к сбою инструмента или наводнению вашего терминала памятью мусора. –

+0

@StevenLu Вы поняли, что не так с методами? Как я могу это исправить? –

5

Следующий код работает для меня.

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

Метод Elazar работал для меня, кроме случаев, когда был задействован макрос. Следующая коррекция разрешила его:

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)); 
} 
Смежные вопросы