From e06f9472c1012235de02caf6e2d5b41688b72c85 Mon Sep 17 00:00:00 2001 From: Jacob Dufault Date: Sun, 5 Mar 2017 15:44:20 -0800 Subject: [PATCH] better templates, index some initializer list values --- indexer.cpp | 34 +++++- libclangmm/Cursor.cc | 4 + libclangmm/Cursor.h | 3 +- test.cc | 2 +- tests/foobar.cc | 3 + .../implicit_variable_instantiation.cc | 63 ++++++++++ tests/usage/var_usage_cstyle_cast.cc | 111 ++++++++++++++++++ 7 files changed, 217 insertions(+), 3 deletions(-) create mode 100644 tests/templates/implicit_variable_instantiation.cc create mode 100644 tests/usage/var_usage_cstyle_cast.cc diff --git a/indexer.cpp b/indexer.cpp index be94673f..086bf161 100644 --- a/indexer.cpp +++ b/indexer.cpp @@ -354,6 +354,10 @@ void VisitDeclForTypeUsageVisitorHandler(clang::Cursor cursor, VisitDeclForTypeU IndexedFile* db = param->db; std::string referenced_usr = cursor.get_referenced().template_specialization_to_template_definition().get_usr(); + // TODO: things in STL cause this to be empty. Figure out why and document it. + if (referenced_usr == "") + return; + TypeId ref_type_id = db->ToTypeId(referenced_usr); if (!param->initial_type) @@ -384,8 +388,25 @@ clang::VisiterResult VisitDeclForTypeUsageVisitor(clang::Cursor cursor, clang::C } param->previous_cursor = cursor; + break; + + + // We do not want to recurse for everything, since if we do that we will end + // up visiting method definition bodies/etc. Instead, we only recurse for + // things that can logically appear as part of an inline variable initializer, + // ie, + // + // class Foo { + // int x = (Foo)3; + // } + case CXCursor_CallExpr: + case CXCursor_CStyleCastExpr: + case CXCursor_CXXStaticCastExpr: + case CXCursor_CXXReinterpretCastExpr: + return clang::VisiterResult::Recurse; } + return clang::VisiterResult::Continue; } @@ -408,6 +429,10 @@ optional ResolveToDeclarationType(IndexedFile* db, clang::Cursor cursor) optional AddDeclUsages(IndexedFile* db, clang::Cursor decl_cursor, bool is_interesting, const CXIdxContainerInfo* semantic_container, const CXIdxContainerInfo* lexical_container) { + + //std::cerr << std::endl << "AddDeclUsages " << decl_cursor.get_spelling() << std::endl; + //Dump(decl_cursor); + // // The general AST format for definitions follows this pattern: // @@ -534,6 +559,13 @@ void indexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) { case CXIdxEntity_CXXStaticVariable: { clang::Cursor decl_cursor = decl->cursor; + + // Do not index implicit template instantiations. + if (decl_cursor != decl_cursor.template_specialization_to_template_definition()) + break; + + std::string decl_usr = decl_cursor.get_usr(); + VarId var_id = db->ToVarId(decl->entityInfo->USR); IndexedVarDef* var_def = db->Resolve(var_id); @@ -969,7 +1001,7 @@ IndexedFile Parse(std::string filename, std::vector args, bool dump NamespaceHelper ns; IndexParam param(&db, &ns); clang_indexTranslationUnit(index_action, ¶m, callbacks, sizeof(callbacks), - CXIndexOpt_IndexFunctionLocalSymbols | CXIndexOpt_SkipParsedBodiesInSession | CXIndexOpt_IndexImplicitTemplateInstantiations, tu.cx_tu); + CXIndexOpt_IndexFunctionLocalSymbols | CXIndexOpt_SkipParsedBodiesInSession, tu.cx_tu); clang_IndexAction_dispose(index_action); diff --git a/libclangmm/Cursor.cc b/libclangmm/Cursor.cc index 586ad76b..b8299ab0 100644 --- a/libclangmm/Cursor.cc +++ b/libclangmm/Cursor.cc @@ -106,6 +106,10 @@ bool Cursor::operator==(const Cursor& rhs) const { return clang_equalCursors(cx_cursor, rhs.cx_cursor); } +bool Cursor::operator!=(const Cursor& rhs) const { + return !(*this == rhs); +} + CXCursorKind Cursor::get_kind() const { return cx_cursor.kind; } diff --git a/libclangmm/Cursor.h b/libclangmm/Cursor.h index c6d080b6..916bbc04 100644 --- a/libclangmm/Cursor.h +++ b/libclangmm/Cursor.h @@ -47,8 +47,9 @@ public: Cursor(); Cursor(const CXCursor& other); - operator bool() const; + explicit operator bool() const; bool operator==(const Cursor& rhs) const; + bool operator!=(const Cursor& rhs) const; CXCursorKind get_kind() const; Type get_type() const; diff --git a/test.cc b/test.cc index b15d40ff..c5abb6ed 100644 --- a/test.cc +++ b/test.cc @@ -94,7 +94,7 @@ int main(int argc, char** argv) { */ for (std::string path : GetFilesInFolder("tests", true /*add_folder_to_path*/)) { - //if (path == "tests/foobar.cc") continue; + //if (path != "tests/usage/var_usage_cstyle_cast.cc") continue; //if (path == "tests/inheritance/class_inherit_templated_parent.cc") continue; //if (path != "tests/templates/template_class_type_usage_folded_into_one.cc") continue; diff --git a/tests/foobar.cc b/tests/foobar.cc index c719bc2a..b0188667 100644 --- a/tests/foobar.cc +++ b/tests/foobar.cc @@ -9,6 +9,9 @@ struct Foo { Foo::Inner a; Foo b; +//#include + + #if false // We could store how many template parameters Foo has and then skip that many TypeRefs..., diff --git a/tests/templates/implicit_variable_instantiation.cc b/tests/templates/implicit_variable_instantiation.cc new file mode 100644 index 00000000..000ab707 --- /dev/null +++ b/tests/templates/implicit_variable_instantiation.cc @@ -0,0 +1,63 @@ +namespace ns { + enum VarType {}; + + template + struct Holder { + static constexpr VarType static_var = (VarType)0x0; + }; + + template + const typename VarType Holder<_>::static_var; + + + int Foo = Holder::static_var; + int Foo2 = Holder::static_var; +} + +/* +OUTPUT: +{ + "types": [{ + "id": 0, + "usr": "c:@N@ns@E@VarType", + "short_name": "VarType", + "qualified_name": "ns::VarType", + "definition": "1:2:8", + "uses": ["*1:2:8", "*1:6:22", "*1:6:44", "*1:10:18"] + }, { + "id": 1, + "usr": "c:@N@ns@ST>1#T@Holder", + "short_name": "Holder", + "qualified_name": "ns::Holder", + "definition": "1:5:10", + "vars": [0], + "uses": ["*1:5:10", "*1:10:26", "1:13:13", "1:14:14"] + }], + "functions": [], + "variables": [{ + "id": 0, + "usr": "c:@N@ns@ST>1#T@Holder@static_var", + "short_name": "static_var", + "qualified_name": "ns::Holder::static_var", + "declaration": "1:6:30", + "definition": "1:10:37", + "variable_type": 0, + "declaring_type": 1, + "uses": ["1:6:30", "1:10:37", "1:13:26", "1:14:27"] + }, { + "id": 1, + "usr": "c:@N@ns@Foo", + "short_name": "Foo", + "qualified_name": "ns::Foo", + "definition": "1:13:7", + "uses": ["1:13:7"] + }, { + "id": 2, + "usr": "c:@N@ns@Foo2", + "short_name": "Foo2", + "qualified_name": "ns::Foo2", + "definition": "1:14:7", + "uses": ["1:14:7"] + }] +} +*/ \ No newline at end of file diff --git a/tests/usage/var_usage_cstyle_cast.cc b/tests/usage/var_usage_cstyle_cast.cc new file mode 100644 index 00000000..2e1f6e28 --- /dev/null +++ b/tests/usage/var_usage_cstyle_cast.cc @@ -0,0 +1,111 @@ +enum VarType {}; + +struct Holder { + static constexpr VarType static_var = (VarType)0x0; +}; + +const VarType Holder::static_var; + + +/* +OUTPUT: +{ + "types": [{ + "id": 0, + "usr": "c:@E@VarType", + "short_name": "VarType", + "qualified_name": "VarType", + "definition": "1:1:6", + "uses": ["*1:1:6", "*1:4:20", "*1:4:42", "*1:7:7"] + }, { + "id": 1, + "usr": "c:@S@Holder", + "short_name": "Holder", + "qualified_name": "Holder", + "definition": "1:3:8", + "vars": [0], + "uses": ["*1:3:8", "1:7:15"] + }], + "functions": [], + "variables": [{ + "id": 0, + "usr": "c:@S@Holder@static_var", + "short_name": "static_var", + "qualified_name": "Holder::static_var", + "declaration": "1:4:28", + "definition": "1:7:23", + "variable_type": 0, + "declaring_type": 1, + "uses": ["1:4:28", "1:7:23"] + }] +} +*/ + + + + + + + + + + + + + + + + + + + + + + + + + +//#include +//#include + +//#include +//#include +//#include +//#include +//#include +//#include +//#include +//#include +//#include +//#include +//#include +//#include +//#include +//#include +//#include +//#include +//#include +//#include +//#include +//#include +//#include +//#include +//#include +//#include +//#include +//#include +//#include +//#include +//#include +//#include +//#include +//#include +//#include +//#include +//#include +//#include +//#include +//#include +//#include +//#include +//#include \ No newline at end of file