У меня есть следующий код, который использует 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()
когда в коде у меня есть одно объявление?
Когда вы используете clang_getCursorReferenced
вы получите CXCursor
на который ссылаются в текущем местоположении. Например, объявление функции ссылается на себя, и на него ссылаются соответствующие вызовы функций. Таким образом, в вашем примере вы получите положительные совпадения для каждой ссылки на объявление функции (либо само объявление функции, либо вызов функции).
Теперь другое дело, что каждый CXCursor
представляет собой часть AST, либо лист, либо более сложную часть с частями. Например, при обходе AST вы по очереди найдете следующие курсоры:
return getSum (c, b)
getSum (c, b)
getSum
Все эти курсоры ссылаются на getSum
объявление функции, и я предполагаю, что это курсоры, которые вызывают несколько ссылок на getSum
,
Вы можете проверить, какая часть исходного кода соответствует текущему курсору, вызвав clang_getCursorExtent
Я никогда не использовал лязг, но на основе документация 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.
*/
...
}