libclang возвращает слишком много информации о объявлениях функций

У меня есть следующий код, который использует API Clang-C.

#include <iostream>
#include <string>
#include <clang-c/Index.h>

CXChildVisitResult printVisitor(CXCursor cursor, CXCursor parent, CXClientData client_data)
{
CXCursor cursor1 = clang_getCursorReferenced(cursor);

CXType type = clang_getCursorType(cursor1);
CXCursorKind kind = clang_getCursorKind(cursor1);
CXString str = clang_getTypeSpelling(type);
CXString str1 = clang_getCursorSpelling(cursor1);
std::string cstr = clang_getCString(str);
std::string cstr1 = clang_getCString(str1);

if(type.kind != 0 && kind == CXCursorKind::CXCursor_FunctionDecl)
{
std::cout << "Declaration!\n" << "type is: " << cstr << std::endl;
std::cout << "name is: " << cstr1 << std::endl;
}

return CXChildVisit_Recurse;
}

int main (int argc, char** argv)
{
CXIndex index = clang_createIndex (
false, // excludeDeclarationFromPCH
true   // displayDiagnostics
);
CXTranslationUnit unit = clang_parseTranslationUnit (
index,                           // CIdx
"main1.cpp",                      // source_filename
argv + 1 ,                        // command_line_args
argc - 1 ,                        // num_command_line_args
0,                                // unsave_files
0,                                // num_unsaved_files
CXTranslationUnit_None           // options
);
if (unit != 0 )
std::cout << "Translation unit successfully created" << std::endl;
else
std::cout << "Translation unit was not created" << std::endl;

CXCursor rootCursor = clang_getTranslationUnitCursor(unit);

clang_visitChildren(rootCursor, printVisitor, NULL);clang_disposeTranslationUnit(unit);
clang_disposeIndex(index);
}

Этот код разбирает следующее.

double getSum(double a, float b)
{
return a + b;
}

int main(void)
{
int a = 5;
float b = 6;
double c = a + b;
return getSum(c, b);
}

Когда программа запускается, я вижу следующее.

    Translation unit successfully created
Declaration!
type is: double (double, float)
name is: getSum
Declaration!
type is: int ()
name is: main
Declaration!
type is: double (double, float)
name is: getSum
Declaration!
type is: double (double, float)
name is: getSum
Declaration!
type is: double (double, float)
name is: getSum
Declaration!
type is: double (double, float)
name is: getSum

Почему я получаю так много деклараций getSum()когда в коде у меня есть одно объявление?

7

Решение

Когда вы используете clang_getCursorReferencedвы получите CXCursor на который ссылаются в текущем местоположении. Например, объявление функции ссылается на себя, и на него ссылаются соответствующие вызовы функций. Таким образом, в вашем примере вы получите положительные совпадения для каждой ссылки на объявление функции (либо само объявление функции, либо вызов функции).

Теперь другое дело, что каждый CXCursor представляет собой часть AST, либо лист, либо более сложную часть с частями. Например, при обходе AST вы по очереди найдете следующие курсоры:

  • return getSum (c, b)
  • getSum (c, b)
  • getSum

Все эти курсоры ссылаются на getSum объявление функции, и я предполагаю, что это курсоры, которые вызывают несколько ссылок на getSum,

Вы можете проверить, какая часть исходного кода соответствует текущему курсору, вызвав clang_getCursorExtent

5

Другие решения

Я никогда не использовал лязг, но на основе документация CXCursor кажется, что CXCursorKind всегда будет Declaration всякий раз, когда курсор где-то в функции (main может получить специальное лечение, я полагаю). Это может объяснить, почему у вас есть несколько отчетов о декларации Sum,

Я основываю свою гипотезу на определении CXCursorKind, найденный Вот:

enum CXCursorKind {
/* Declarations */
/**
* \brief A declaration whose specific kind is not exposed via this
* interface.
*
* Unexposed declarations have the same operations as any other kind
* of declaration; one can extract their location information,
* spelling, find their definitions, etc. However, the specific kind
* of the declaration is not reported.
*/
...
}
2

По вопросам рекламы [email protected]