mirror of
https://github.com/MaskRay/ccls.git
synced 2024-11-22 15:45:08 +00:00
Support llvm 4
This commit is contained in:
parent
c079ab45b3
commit
ebd467d31b
107
indexer.cpp
107
indexer.cpp
@ -84,7 +84,7 @@ IndexedTypeDef::IndexedTypeDef(TypeId id, const std::string& usr) : id(id), def(
|
||||
//std::cerr << "Creating type with usr " << usr << std::endl;
|
||||
}
|
||||
|
||||
void IndexedTypeDef::AddUsage(Location loc, bool insert_if_not_present) {
|
||||
void AddUsage(std::vector<Location>& uses, Location loc, bool insert_if_not_present = true) {
|
||||
for (int i = uses.size() - 1; i >= 0; --i) {
|
||||
if (uses[i].IsEqualTo(loc)) {
|
||||
if (loc.interesting)
|
||||
@ -395,7 +395,7 @@ void VisitDeclForTypeUsageVisitorHandler(clang::Cursor cursor, VisitDeclForTypeU
|
||||
if (param->is_interesting) {
|
||||
IndexedTypeDef* ref_type_def = db->Resolve(ref_type_id);
|
||||
Location loc = db->id_cache.Resolve(cursor, true /*interesting*/);
|
||||
ref_type_def->AddUsage(loc);
|
||||
AddUsage(ref_type_def->uses, loc);
|
||||
}
|
||||
}
|
||||
|
||||
@ -455,7 +455,7 @@ optional<TypeId> ResolveToDeclarationType(IndexedFile* db, clang::Cursor cursor)
|
||||
// returns the first seen TypeRef or TemplateRef value, which can be useful if trying
|
||||
// to figure out ie, what a using statement refers to. If trying to generally resolve
|
||||
// a cursor to a type, use ResolveToDeclarationType, which works in more scenarios.
|
||||
optional<TypeId> AddDeclUsages(IndexedFile* db, clang::Cursor decl_cursor,
|
||||
optional<TypeId> AddDeclTypeUsages(IndexedFile* db, clang::Cursor decl_cursor,
|
||||
bool is_interesting, const CXIdxContainerInfo* semantic_container,
|
||||
const CXIdxContainerInfo* lexical_container) {
|
||||
|
||||
@ -584,6 +584,70 @@ optional<TypeId> AddDeclUsages(IndexedFile* db, clang::Cursor decl_cursor,
|
||||
return param.initial_type;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Various versions of LLVM (ie, 4.0) will not visit inline variable references for template arguments.
|
||||
clang::VisiterResult AddDeclInitializerUsagesVisitor(clang::Cursor cursor, clang::Cursor parent, IndexedFile* db) {
|
||||
/*
|
||||
We need to index the |DeclRefExpr| below (ie, |var| inside of Foo<int>::var).
|
||||
|
||||
template<typename T>
|
||||
struct Foo {
|
||||
static constexpr int var = 3;
|
||||
};
|
||||
|
||||
int a = Foo<int>::var;
|
||||
|
||||
=>
|
||||
|
||||
VarDecl a
|
||||
UnexposedExpr var
|
||||
DeclRefExpr var
|
||||
TemplateRef Foo
|
||||
|
||||
*/
|
||||
|
||||
switch (cursor.get_kind()) {
|
||||
case CXCursor_DeclRefExpr:
|
||||
CXCursorKind referenced_kind = cursor.get_referenced().get_kind();
|
||||
if (cursor.get_referenced().get_kind() != CXCursor_VarDecl)
|
||||
break;
|
||||
|
||||
// TODO: when we resolve the template type to the definition, we get a different USR.
|
||||
|
||||
//clang::Cursor ref = cursor.get_referenced().template_specialization_to_template_definition().get_type().strip_qualifiers().get_usr();
|
||||
//std::string ref_usr = cursor.get_referenced().template_specialization_to_template_definition().get_type().strip_qualifiers().get_usr();
|
||||
std::string ref_usr = cursor.get_referenced().template_specialization_to_template_definition().get_usr();
|
||||
//std::string ref_usr = ref.get_usr();
|
||||
if (ref_usr == "")
|
||||
break;
|
||||
|
||||
VarId ref_id = db->ToVarId(ref_usr);
|
||||
IndexedVarDef* ref_def = db->Resolve(ref_id);
|
||||
Location loc = db->id_cache.Resolve(cursor, false /*interesting*/);
|
||||
std::cerr << "Adding usage to id=" << ref_id.id << " usr=" << ref_usr << " at " << loc.ToString() << std::endl;
|
||||
AddUsage(ref_def->uses, loc);
|
||||
break;
|
||||
}
|
||||
|
||||
return clang::VisiterResult::Recurse;
|
||||
}
|
||||
|
||||
void AddDeclInitializerUsages(IndexedFile* db, clang::Cursor decl_cursor) {
|
||||
decl_cursor.VisitChildren(&AddDeclInitializerUsagesVisitor, db);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void indexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) {
|
||||
// TODO: we can minimize processing for cursors which return false for clang_Location_isFromMainFile (ie, only add usages)
|
||||
|
||||
@ -595,6 +659,8 @@ void indexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) {
|
||||
IndexedFile* db = param->db;
|
||||
NamespaceHelper* ns = param->ns;
|
||||
|
||||
// std::cerr << "DECL kind=" << decl->entityInfo->kind << " at " << db->id_cache.Resolve(decl->cursor, false).ToPrettyString(&db->id_cache) << std::endl;
|
||||
|
||||
switch (decl->entityInfo->kind) {
|
||||
case CXIdxEntity_CXXNamespace:
|
||||
{
|
||||
@ -632,16 +698,19 @@ void indexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) {
|
||||
var_def->def.definition = decl_loc;
|
||||
else
|
||||
var_def->def.declaration = decl_loc;
|
||||
var_def->uses.push_back(decl_loc);
|
||||
AddUsage(var_def->uses, decl_loc);
|
||||
|
||||
//std::cerr << std::endl << "Visiting declaration" << std::endl;
|
||||
//Dump(decl_cursor);
|
||||
|
||||
AddDeclInitializerUsages(db, decl_cursor);
|
||||
var_def = db->Resolve(var_id);
|
||||
|
||||
// Declaring variable type information. Note that we do not insert an
|
||||
// interesting reference for parameter declarations - that is handled when
|
||||
// the function declaration is encountered since we won't receive ParmDecl
|
||||
// declarations for unnamed parameters.
|
||||
AddDeclUsages(db, decl_cursor, decl_cursor.get_kind() != CXCursor_ParmDecl /*is_interesting*/, decl->semanticContainer, decl->lexicalContainer);
|
||||
AddDeclTypeUsages(db, decl_cursor, decl_cursor.get_kind() != CXCursor_ParmDecl /*is_interesting*/, decl->semanticContainer, decl->lexicalContainer);
|
||||
optional<TypeId> var_type = ResolveToDeclarationType(db, decl_cursor);
|
||||
if (var_type.has_value())
|
||||
var_def->def.variable_type = var_type.value();
|
||||
@ -672,10 +741,10 @@ void indexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) {
|
||||
|
||||
Location decl_loc = db->id_cache.Resolve(decl->loc, false /*interesting*/);
|
||||
|
||||
func_def->uses.push_back(decl_loc);
|
||||
AddUsage(func_def->uses, 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);
|
||||
AddDeclTypeUsages(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.
|
||||
@ -712,7 +781,7 @@ void indexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) {
|
||||
// TODO: Should it be interesting?
|
||||
if (is_ctor_or_dtor) {
|
||||
Location type_usage_loc = decl_loc;
|
||||
declaring_type_def->AddUsage(type_usage_loc);
|
||||
AddUsage(declaring_type_def->uses, type_usage_loc);
|
||||
}
|
||||
|
||||
// Register function in declaring type if it hasn't been registered yet.
|
||||
@ -742,7 +811,7 @@ void indexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) {
|
||||
// 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);
|
||||
AddDeclTypeUsages(db, arg, true /*is_interesting*/, decl->semanticContainer, decl->semanticContainer);
|
||||
|
||||
//TypeResolution arg_type = ResolveToType(db, arg.get_type());
|
||||
//if (arg_type.resolved_type)
|
||||
@ -792,7 +861,7 @@ void indexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) {
|
||||
{
|
||||
// Note we want to fetch the first TypeRef. Running ResolveCursorType(decl->cursor) would return
|
||||
// the type of the typedef/using, not the type of the referenced type.
|
||||
optional<TypeId> alias_of = AddDeclUsages(db, decl->cursor, true /*is_interesting*/, decl->semanticContainer, decl->lexicalContainer);
|
||||
optional<TypeId> alias_of = AddDeclTypeUsages(db, decl->cursor, true /*is_interesting*/, decl->semanticContainer, decl->lexicalContainer);
|
||||
|
||||
TypeId type_id = db->ToTypeId(decl->entityInfo->USR);
|
||||
IndexedTypeDef* type_def = db->Resolve(type_id);
|
||||
@ -807,7 +876,7 @@ void indexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) {
|
||||
|
||||
Location decl_loc = db->id_cache.Resolve(decl->loc, true /*interesting*/);
|
||||
type_def->def.definition = decl_loc.WithInteresting(false);
|
||||
type_def->AddUsage(decl_loc);
|
||||
AddUsage(type_def->uses, decl_loc);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -841,7 +910,7 @@ void indexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) {
|
||||
assert(decl->isDefinition);
|
||||
Location decl_loc = db->id_cache.Resolve(decl->loc, true /*interesting*/);
|
||||
type_def->def.definition = decl_loc.WithInteresting(false);
|
||||
type_def->AddUsage(decl_loc);
|
||||
AddUsage(type_def->uses, decl_loc);
|
||||
|
||||
//type_def->alias_of
|
||||
//type_def->funcs
|
||||
@ -855,7 +924,7 @@ void indexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) {
|
||||
for (unsigned int i = 0; i < class_info->numBases; ++i) {
|
||||
const CXIdxBaseClassInfo* base_class = class_info->bases[i];
|
||||
|
||||
AddDeclUsages(db, base_class->cursor, true /*is_interesting*/, decl->semanticContainer, decl->lexicalContainer);
|
||||
AddDeclTypeUsages(db, base_class->cursor, true /*is_interesting*/, decl->semanticContainer, decl->lexicalContainer);
|
||||
optional<TypeId> parent_type_id = ResolveToDeclarationType(db, base_class->cursor);
|
||||
IndexedTypeDef* type_def = db->Resolve(type_id); // type_def ptr could be invalidated by ResolveDeclToType.
|
||||
if (parent_type_id) {
|
||||
@ -901,6 +970,8 @@ void indexEntityReference(CXClientData client_data, const CXIdxEntityRefInfo* re
|
||||
IndexedFile* db = param->db;
|
||||
clang::Cursor cursor(ref->cursor);
|
||||
|
||||
//std::cerr << "REF kind=" << ref->referencedEntity->kind << " at " << db->id_cache.Resolve(cursor, false).ToPrettyString(&db->id_cache) << std::endl;
|
||||
|
||||
switch (ref->referencedEntity->kind) {
|
||||
case CXIdxEntity_CXXNamespace:
|
||||
{
|
||||
@ -919,7 +990,7 @@ void indexEntityReference(CXClientData client_data, const CXIdxEntityRefInfo* re
|
||||
VarId var_id = db->ToVarId(referenced.get_usr());
|
||||
IndexedVarDef* var_def = db->Resolve(var_id);
|
||||
Location loc = db->id_cache.Resolve(ref->loc, false /*interesting*/);
|
||||
var_def->uses.push_back(loc);
|
||||
AddUsage(var_def->uses, loc);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -954,11 +1025,11 @@ void indexEntityReference(CXClientData client_data, const CXIdxEntityRefInfo* re
|
||||
|
||||
caller_def->def.callees.push_back(FuncRef(called_id, loc));
|
||||
called_def->callers.push_back(FuncRef(caller_id, loc));
|
||||
called_def->uses.push_back(loc);
|
||||
AddUsage(called_def->uses, loc);
|
||||
}
|
||||
else {
|
||||
IndexedFuncDef* called_def = db->Resolve(called_id);
|
||||
called_def->uses.push_back(loc);
|
||||
AddUsage(called_def->uses, loc);
|
||||
}
|
||||
|
||||
// For constructor/destructor, also add a usage against the type. Clang
|
||||
@ -978,7 +1049,7 @@ void indexEntityReference(CXClientData client_data, const CXIdxEntityRefInfo* re
|
||||
if (called_def->def.declaring_type) {
|
||||
//assert(called_def->def.declaring_type.has_value());
|
||||
IndexedTypeDef* type_def = db->Resolve(called_def->def.declaring_type.value());
|
||||
type_def->AddUsage(our_loc);
|
||||
AddUsage(type_def->uses, our_loc);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1021,7 +1092,7 @@ void indexEntityReference(CXClientData client_data, const CXIdxEntityRefInfo* re
|
||||
// Foo f;
|
||||
// }
|
||||
//
|
||||
referenced_def->AddUsage(db->id_cache.Resolve(ref->loc, false /*interesting*/));
|
||||
AddUsage(referenced_def->uses, db->id_cache.Resolve(ref->loc, false /*interesting*/));
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -332,7 +332,6 @@ struct IndexedTypeDef {
|
||||
IndexedTypeDef() : def("") {} // For serialization
|
||||
|
||||
IndexedTypeDef(TypeId id, const std::string& usr);
|
||||
void AddUsage(Location loc, bool insert_if_not_present = true);
|
||||
|
||||
bool operator<(const IndexedTypeDef& other) const {
|
||||
return def.usr < other.def.usr;
|
||||
|
4
test.cc
4
test.cc
@ -97,10 +97,10 @@ void RunTests() {
|
||||
|
||||
for (std::string path : GetFilesInFolder("tests", true /*recursive*/, true /*add_folder_to_path*/)) {
|
||||
//if (path != "tests/templates/specialized_func_definition.cc") continue;
|
||||
//if (path != "tests/outline/outline2.cc") continue;
|
||||
//if (path != "tests/templates/namespace_template_class_template_func_usage_folded_into_one.cc") continue;
|
||||
//if (path == "tests/inheritance/class_inherit_templated_parent.cc") continue;
|
||||
//if (path != "tests/namespaces/namespace_reference.cc") continue;
|
||||
//if (path != "tests/stl.cc") continue;
|
||||
//if (path != "tests/templates/implicit_variable_instantiation.cc") continue;
|
||||
|
||||
//if (path != "tests/templates/template_class_type_usage_folded_into_one.cc") continue;
|
||||
//path = "C:/Users/jacob/Desktop/superindex/indexer/" + path;
|
||||
|
@ -7,8 +7,7 @@ T var = 3;
|
||||
int a = var<A>;
|
||||
int b = var<B>;
|
||||
|
||||
// TODO: No usages of types on var.
|
||||
// libclang doesn't expose the info. File a bug.
|
||||
// NOTE: libclang before 4.0 doesn't expose template usage on |var|.
|
||||
|
||||
#if false
|
||||
EnumDecl A
|
||||
@ -48,11 +47,11 @@ OUTPUT:
|
||||
}],
|
||||
"vars": [{
|
||||
"id": 0,
|
||||
"usr": "c:@var",
|
||||
"usr": "c:@VT>1#T@var",
|
||||
"short_name": "var",
|
||||
"qualified_name": "var",
|
||||
"definition": "1:5:3",
|
||||
"uses": ["1:5:3"]
|
||||
"uses": ["1:5:3", "1:7:9", "1:8:9"]
|
||||
}, {
|
||||
"id": 1,
|
||||
"usr": "c:@a",
|
||||
|
Loading…
Reference in New Issue
Block a user