|
|
@ -540,15 +540,16 @@ optional<TypeId> AddDeclUsages(IndexedFile* db, clang::Cursor decl_cursor, |
|
|
|
VisitDeclForTypeUsageVisitorHandler(param.previous_cursor.value(), ¶m); |
|
|
|
} |
|
|
|
else { |
|
|
|
// If we are not processing the last type ref, it *must* be a TypeRef (ie,
|
|
|
|
// and not a TemplateRef).
|
|
|
|
// If we are not processing the last type ref, it *must* be a TypeRef or
|
|
|
|
// TemplateRef.
|
|
|
|
//
|
|
|
|
// We will not visit every child if the is_interseting is false, so previous_cursor
|
|
|
|
// may not point to the last TemplateRef.
|
|
|
|
assert( |
|
|
|
is_interesting == false || |
|
|
|
param.previous_cursor.has_value() == false || |
|
|
|
param.previous_cursor.value().get_kind() == CXCursor_TypeRef); |
|
|
|
(param.previous_cursor.value().get_kind() == CXCursor_TypeRef || |
|
|
|
param.previous_cursor.value().get_kind() == CXCursor_TemplateRef)); |
|
|
|
} |
|
|
|
|
|
|
|
return param.initial_type; |
|
|
@ -632,105 +633,114 @@ void indexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) { |
|
|
|
case CXIdxEntity_CXXConversionFunction: |
|
|
|
{ |
|
|
|
clang::Cursor decl_cursor = decl->cursor; |
|
|
|
FuncId func_id = db->ToFuncId(decl->entityInfo->USR); |
|
|
|
IndexedFuncDef* func_def = db->Resolve(func_id); |
|
|
|
|
|
|
|
func_def->is_bad_def = is_system_def; |
|
|
|
clang::Cursor resolved = decl_cursor.template_specialization_to_template_definition(); |
|
|
|
|
|
|
|
// TODO: Eventually run with this if. Right now I want to iron out bugs this may shadow.
|
|
|
|
//if (!decl->isRedeclaration) {
|
|
|
|
func_def->def.short_name = decl->entityInfo->name; |
|
|
|
func_def->def.qualified_name = ns->QualifiedName(decl->semanticContainer, func_def->def.short_name); |
|
|
|
//}
|
|
|
|
FuncId func_id = db->ToFuncId(resolved.cx_cursor); |
|
|
|
IndexedFuncDef* func_def = db->Resolve(func_id); |
|
|
|
|
|
|
|
Location decl_loc = db->id_cache.Resolve(decl->loc, false /*interesting*/); |
|
|
|
if (decl->isDefinition) |
|
|
|
|
|
|
|
func_def->uses.push_back(decl_loc); |
|
|
|
// We don't actually need to know the return type, but we need to mark it
|
|
|
|
// as an interesting usage.
|
|
|
|
AddDeclUsages(db, decl_cursor, true /*is_interesting*/, decl->semanticContainer, decl->lexicalContainer); |
|
|
|
|
|
|
|
// TODO: support multiple definitions per function; right now we are hacking the 'declarations' field by
|
|
|
|
// adding a definition when we really don't have one.
|
|
|
|
if (decl->isDefinition && !func_def->def.definition.has_value()) |
|
|
|
func_def->def.definition = decl_loc; |
|
|
|
else |
|
|
|
func_def->declarations.push_back(decl_loc); |
|
|
|
func_def->uses.push_back(decl_loc); |
|
|
|
|
|
|
|
bool is_pure_virtual = clang_CXXMethod_isPureVirtual(decl->cursor); |
|
|
|
bool is_ctor_or_dtor = decl->entityInfo->kind == CXIdxEntity_CXXConstructor || decl->entityInfo->kind == CXIdxEntity_CXXDestructor; |
|
|
|
//bool process_declaring_type = is_pure_virtual || is_ctor_or_dtor;
|
|
|
|
|
|
|
|
// Add function usage information. We only want to do it once per
|
|
|
|
// definition/declaration. Do it on definition since there should only ever
|
|
|
|
// be one of those in the entire program.
|
|
|
|
if (IsTypeDefinition(decl->semanticContainer)) { |
|
|
|
TypeId declaring_type_id = db->ToTypeId(decl->semanticContainer->cursor); |
|
|
|
IndexedTypeDef* declaring_type_def = db->Resolve(declaring_type_id); |
|
|
|
func_def->def.declaring_type = declaring_type_id; |
|
|
|
// If decl_cursor != resolved, then decl_cursor is a template specialization. We
|
|
|
|
// don't want to override a lot of the function definition information in that
|
|
|
|
// scenario.
|
|
|
|
if (decl_cursor == resolved) { |
|
|
|
func_def->is_bad_def = is_system_def; |
|
|
|
|
|
|
|
// TODO: Eventually run with this if. Right now I want to iron out bugs this may shadow.
|
|
|
|
//if (!decl->isRedeclaration) {
|
|
|
|
func_def->def.short_name = decl->entityInfo->name; |
|
|
|
func_def->def.qualified_name = ns->QualifiedName(decl->semanticContainer, func_def->def.short_name); |
|
|
|
//}
|
|
|
|
|
|
|
|
bool is_pure_virtual = clang_CXXMethod_isPureVirtual(decl->cursor); |
|
|
|
bool is_ctor_or_dtor = decl->entityInfo->kind == CXIdxEntity_CXXConstructor || decl->entityInfo->kind == CXIdxEntity_CXXDestructor; |
|
|
|
//bool process_declaring_type = is_pure_virtual || is_ctor_or_dtor;
|
|
|
|
|
|
|
|
// Add function usage information. We only want to do it once per
|
|
|
|
// definition/declaration. Do it on definition since there should only ever
|
|
|
|
// be one of those in the entire program.
|
|
|
|
if (IsTypeDefinition(decl->semanticContainer)) { |
|
|
|
TypeId declaring_type_id = db->ToTypeId(decl->semanticContainer->cursor); |
|
|
|
IndexedTypeDef* declaring_type_def = db->Resolve(declaring_type_id); |
|
|
|
func_def->def.declaring_type = declaring_type_id; |
|
|
|
|
|
|
|
// Mark a type reference at the ctor/dtor location.
|
|
|
|
// TODO: Should it be interesting?
|
|
|
|
if (is_ctor_or_dtor) { |
|
|
|
Location type_usage_loc = decl_loc; |
|
|
|
declaring_type_def->AddUsage(type_usage_loc); |
|
|
|
} |
|
|
|
|
|
|
|
// Mark a type reference at the ctor/dtor location.
|
|
|
|
// TODO: Should it be interesting?
|
|
|
|
if (is_ctor_or_dtor) { |
|
|
|
Location type_usage_loc = decl_loc; |
|
|
|
declaring_type_def->AddUsage(type_usage_loc); |
|
|
|
// Register function in declaring type if it hasn't been registered yet.
|
|
|
|
if (!Contains(declaring_type_def->def.funcs, func_id)) |
|
|
|
declaring_type_def->def.funcs.push_back(func_id); |
|
|
|
} |
|
|
|
|
|
|
|
// Register function in declaring type if it hasn't been registered yet.
|
|
|
|
if (!Contains(declaring_type_def->def.funcs, func_id)) |
|
|
|
declaring_type_def->def.funcs.push_back(func_id); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// We don't actually need to know the return type, but we need to mark it
|
|
|
|
// as an interesting usage.
|
|
|
|
AddDeclUsages(db, decl_cursor, true /*is_interesting*/, decl->semanticContainer, decl->lexicalContainer); |
|
|
|
|
|
|
|
//TypeResolution ret_type = ResolveToType(db, decl_cursor.get_type().get_return_type());
|
|
|
|
//if (ret_type.resolved_type)
|
|
|
|
// AddInterestingUsageToType(db, ret_type, FindLocationOfTypeSpecifier(decl_cursor));
|
|
|
|
|
|
|
|
if (decl->isDefinition || is_pure_virtual) { |
|
|
|
// Mark type usage for parameters as interesting. We handle this here
|
|
|
|
// instead of inside var declaration because clang will not emit a var
|
|
|
|
// declaration for an unnamed parameter, but we still want to mark the
|
|
|
|
// usage as interesting.
|
|
|
|
// TODO: Do a similar thing for function decl parameter usages. Mark
|
|
|
|
// prototype params as interesting type usages but also relate mark
|
|
|
|
// them as as usages on the primary variable - requires USR to be
|
|
|
|
// the same. We can work around it by declaring which variables a
|
|
|
|
// parameter has declared and update the USR in the definition.
|
|
|
|
clang::Cursor cursor = decl->cursor; |
|
|
|
for (clang::Cursor arg : cursor.get_arguments()) { |
|
|
|
switch (arg.get_kind()) { |
|
|
|
case CXCursor_ParmDecl: |
|
|
|
// We don't need to know the arg type, but we do want to mark it as
|
|
|
|
// an interesting usage. Note that we use semanticContainer twice
|
|
|
|
// because a parameter is not really part of the lexical container.
|
|
|
|
AddDeclUsages(db, arg, true /*is_interesting*/, decl->semanticContainer, decl->semanticContainer); |
|
|
|
|
|
|
|
//TypeResolution arg_type = ResolveToType(db, arg.get_type());
|
|
|
|
//if (arg_type.resolved_type)
|
|
|
|
// AddInterestingUsageToType(db, arg_type, FindLocationOfTypeSpecifier(arg));
|
|
|
|
break; |
|
|
|
//TypeResolution ret_type = ResolveToType(db, decl_cursor.get_type().get_return_type());
|
|
|
|
//if (ret_type.resolved_type)
|
|
|
|
// AddInterestingUsageToType(db, ret_type, FindLocationOfTypeSpecifier(decl_cursor));
|
|
|
|
|
|
|
|
if (decl->isDefinition || is_pure_virtual) { |
|
|
|
// Mark type usage for parameters as interesting. We handle this here
|
|
|
|
// instead of inside var declaration because clang will not emit a var
|
|
|
|
// declaration for an unnamed parameter, but we still want to mark the
|
|
|
|
// usage as interesting.
|
|
|
|
// TODO: Do a similar thing for function decl parameter usages. Mark
|
|
|
|
// prototype params as interesting type usages but also relate mark
|
|
|
|
// them as as usages on the primary variable - requires USR to be
|
|
|
|
// the same. We can work around it by declaring which variables a
|
|
|
|
// parameter has declared and update the USR in the definition.
|
|
|
|
clang::Cursor cursor = decl->cursor; |
|
|
|
for (clang::Cursor arg : cursor.get_arguments()) { |
|
|
|
switch (arg.get_kind()) { |
|
|
|
case CXCursor_ParmDecl: |
|
|
|
// We don't need to know the arg type, but we do want to mark it as
|
|
|
|
// an interesting usage. Note that we use semanticContainer twice
|
|
|
|
// because a parameter is not really part of the lexical container.
|
|
|
|
AddDeclUsages(db, arg, true /*is_interesting*/, decl->semanticContainer, decl->semanticContainer); |
|
|
|
|
|
|
|
//TypeResolution arg_type = ResolveToType(db, arg.get_type());
|
|
|
|
//if (arg_type.resolved_type)
|
|
|
|
// AddInterestingUsageToType(db, arg_type, FindLocationOfTypeSpecifier(arg));
|
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Process inheritance.
|
|
|
|
//void clang_getOverriddenCursors(CXCursor cursor, CXCursor **overridden, unsigned *num_overridden);
|
|
|
|
//void clang_disposeOverriddenCursors(CXCursor *overridden);
|
|
|
|
if (clang_CXXMethod_isVirtual(decl->cursor)) { |
|
|
|
CXCursor* overridden; |
|
|
|
unsigned int num_overridden; |
|
|
|
clang_getOverriddenCursors(decl->cursor, &overridden, &num_overridden); |
|
|
|
// Process inheritance.
|
|
|
|
//void clang_getOverriddenCursors(CXCursor cursor, CXCursor **overridden, unsigned *num_overridden);
|
|
|
|
//void clang_disposeOverriddenCursors(CXCursor *overridden);
|
|
|
|
if (clang_CXXMethod_isVirtual(decl->cursor)) { |
|
|
|
CXCursor* overridden; |
|
|
|
unsigned int num_overridden; |
|
|
|
clang_getOverriddenCursors(decl->cursor, &overridden, &num_overridden); |
|
|
|
|
|
|
|
// TODO: How to handle multiple parent overrides??
|
|
|
|
for (unsigned int i = 0; i < num_overridden; ++i) { |
|
|
|
clang::Cursor parent = overridden[i]; |
|
|
|
FuncId parent_id = db->ToFuncId(parent.get_usr()); |
|
|
|
IndexedFuncDef* parent_def = db->Resolve(parent_id); |
|
|
|
func_def = db->Resolve(func_id); // ToFuncId invalidated func_def
|
|
|
|
// TODO: How to handle multiple parent overrides??
|
|
|
|
for (unsigned int i = 0; i < num_overridden; ++i) { |
|
|
|
clang::Cursor parent = overridden[i]; |
|
|
|
FuncId parent_id = db->ToFuncId(parent.get_usr()); |
|
|
|
IndexedFuncDef* parent_def = db->Resolve(parent_id); |
|
|
|
func_def = db->Resolve(func_id); // ToFuncId invalidated func_def
|
|
|
|
|
|
|
|
func_def->def.base = parent_id; |
|
|
|
parent_def->derived.push_back(func_id); |
|
|
|
} |
|
|
|
func_def->def.base = parent_id; |
|
|
|
parent_def->derived.push_back(func_id); |
|
|
|
} |
|
|
|
|
|
|
|
clang_disposeOverriddenCursors(overridden); |
|
|
|
clang_disposeOverriddenCursors(overridden); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|