diff --git a/src/indexer.cc b/src/indexer.cc index d27d0960..9b0ce6d3 100644 --- a/src/indexer.cc +++ b/src/indexer.cc @@ -12,6 +12,8 @@ #include #include +// TODO: See if we can use clang_indexLoc_getFileLocation to get a type ref on |Foobar| in DISALLOW_COPY(Foobar) + namespace { const bool kIndexStdDeclarations = true; @@ -22,13 +24,12 @@ void AddFuncRef(std::vector* result, IndexFuncRef ref) { result->push_back(ref); } - -Range Resolve(const CXSourceRange& range) { +Range Resolve(const CXSourceRange& range, CXFile* cx_file = nullptr) { CXSourceLocation start = clang_getRangeStart(range); CXSourceLocation end = clang_getRangeEnd(range); unsigned int start_line, start_column; - clang_getSpellingLocation(start, nullptr, &start_line, &start_column, nullptr); + clang_getSpellingLocation(start, cx_file, &start_line, &start_column, nullptr); unsigned int end_line, end_column; clang_getSpellingLocation(end, nullptr, &end_line, &end_column, nullptr); @@ -37,14 +38,14 @@ Range Resolve(const CXSourceRange& range) { Position(end_line, end_column) /*end*/); } -Range ResolveSpelling(const CXCursor& cx_cursor) { +Range ResolveSpelling(const CXCursor& cx_cursor, CXFile* cx_file = nullptr) { CXSourceRange cx_range = clang_Cursor_getSpellingNameRange(cx_cursor, 0, 0); - return Resolve(cx_range); + return Resolve(cx_range, cx_file); } -Range ResolveExtent(const CXCursor& cx_cursor) { +Range ResolveExtent(const CXCursor& cx_cursor, CXFile* cx_file = nullptr) { CXSourceRange cx_range = clang_getCursorExtent(cx_cursor); - return Resolve(cx_range); + return Resolve(cx_range, cx_file); } @@ -716,7 +717,48 @@ bool AreEqualLocations(CXIdxLoc loc, CXCursor cursor) { +clang::VisiterResult VisitMacroDefinitionAndExpansions(clang::Cursor cursor, clang::Cursor parent, IndexParam* param) { + switch (cursor.get_kind()) { + case CXCursor_MacroDefinition: + case CXCursor_MacroExpansion: + // Resolve location, find IndexFile instance. + CXSourceRange cx_source_range = clang_Cursor_getSpellingNameRange(cursor.cx_cursor, 0, 0); + CXSourceLocation start = clang_getRangeStart(cx_source_range); + if (clang_Location_isInSystemHeader(start)) + break; + CXFile file; + Range decl_loc_spelling = Resolve(cx_source_range, &file); + IndexFile* db = ConsumeFile(param, file); + if (!db) + break; + // TODO: Considering checking clang_Cursor_isMacroFunctionLike, but the + // only real difference will be that we show 'callers' instead of 'refs' + // (especially since macros cannot have overrides) + + std::string decl_usr; + if (cursor.get_kind() == CXCursor_MacroDefinition) + decl_usr = cursor.get_usr(); + else + decl_usr = cursor.get_referenced().get_usr(); + + IndexVarId var_id = db->ToVarId(decl_usr); + IndexVar* var_def = db->Resolve(var_id); + UniqueAdd(var_def->uses, decl_loc_spelling); + + if (cursor.get_kind() == CXCursor_MacroDefinition) { + var_def->def.short_name = cursor.get_display_name(); + var_def->def.detailed_name = var_def->def.short_name; + var_def->def.is_local = false; + var_def->def.definition_spelling = decl_loc_spelling; + var_def->def.definition_extent = ResolveExtent(cursor.cx_cursor);; + } + + break; + } + + return clang::VisiterResult::Continue; +} @@ -1466,6 +1508,8 @@ std::vector> Parse( clang_IndexAction_dispose(index_action); //std::cerr << "!! [END] Indexing " << file << std::endl; + tu.document_cursor().VisitChildren(&VisitMacroDefinitionAndExpansions, ¶m); + perf->index_build = timer.ElapsedMicrosecondsAndReset(); auto result = param.file_consumer->TakeLocalState(); diff --git a/tests/macros/foo.cc b/tests/macros/foo.cc new file mode 100644 index 00000000..561191fd --- /dev/null +++ b/tests/macros/foo.cc @@ -0,0 +1,51 @@ +#define A 5 +#define DISALLOW(type) type(type&&) = delete; + +struct Foo { + DISALLOW(Foo); +}; + +int x = A; + +/* +OUTPUT: +{ + "types": [{ + "id": 0, + "usr": "c:@S@Foo", + "short_name": "Foo", + "detailed_name": "Foo", + "definition_spelling": "4:8-4:11", + "definition_extent": "4:1-6:2", + "uses": ["4:8-4:11"] + }], + "vars": [{ + "id": 0, + "usr": "c:@x", + "short_name": "x", + "detailed_name": "int x", + "definition_spelling": "8:5-8:6", + "definition_extent": "8:1-8:10", + "is_local": false, + "uses": ["8:5-8:6"] + }, { + "id": 1, + "usr": "c:foo.cc@8@macro@A", + "short_name": "A", + "detailed_name": "A", + "definition_spelling": "1:9-1:10", + "definition_extent": "1:9-1:12", + "is_local": false, + "uses": ["1:9-1:10", "8:9-8:10"] + }, { + "id": 2, + "usr": "c:foo.cc@21@macro@DISALLOW", + "short_name": "DISALLOW", + "detailed_name": "DISALLOW", + "definition_spelling": "2:9-2:17", + "definition_extent": "2:9-2:46", + "is_local": false, + "uses": ["2:9-2:17", "5:3-5:11"] + }] +} +*/ diff --git a/tests/usage/func_called_from_macro_argument.cc b/tests/usage/func_called_from_macro_argument.cc index 86d4bfe1..1f1373e6 100644 --- a/tests/usage/func_called_from_macro_argument.cc +++ b/tests/usage/func_called_from_macro_argument.cc @@ -24,6 +24,16 @@ OUTPUT: "definition_spelling": "5:6-5:12", "definition_extent": "5:1-7:2", "callees": ["0@6:14-6:20"] + }], + "vars": [{ + "id": 0, + "usr": "c:func_called_from_macro_argument.cc@8@macro@MACRO_CALL", + "short_name": "MACRO_CALL", + "detailed_name": "MACRO_CALL", + "definition_spelling": "1:9-1:19", + "definition_extent": "1:9-1:24", + "is_local": false, + "uses": ["1:9-1:19", "6:3-6:13"] }] } */ \ No newline at end of file