diff --git a/include/Index/CSIF.h b/include/Index/CSIF.h index d20902fa..20497712 100644 --- a/include/Index/CSIF.h +++ b/include/Index/CSIF.h @@ -71,7 +71,7 @@ struct Relation { /// The role of the relation. Role role; /// The range of the target, maybe empty. - // Range range; + protocol::Range range; }; enum class SymbolKind { diff --git a/include/Index/SymbolSlab.h b/include/Index/SymbolSlab.h index 5e634270..531f28e6 100644 --- a/include/Index/SymbolSlab.h +++ b/include/Index/SymbolSlab.h @@ -6,24 +6,16 @@ namespace clice { class SymbolSlab { public: + CSIF index(clang::ASTContext& context); + + std::size_t lookup(const clang::Decl* decl); + SymbolSlab& addSymbol(const clang::Decl* decl); SymbolSlab& addOccurrence(const clang::Decl* decl, protocol::Range range, Role role); SymbolSlab& addRelation(const clang::Decl* from, const clang::Decl* to, Role role); - std::size_t lookup(const clang::Decl* decl) { - auto iter = cache.find(decl); - if(iter != cache.end()) { - return iter->second; - } - - llvm::outs() << "SymbolSlab::lookup: decl not found\n"; - std::terminate(); - } - - CSIF index(clang::ASTContext& context); - private: llvm::BumpPtrAllocator allocator; llvm::StringSaver saver{allocator}; @@ -31,6 +23,8 @@ private: std::vector symbols; std::vector occurrences; std::vector> relations; + + llvm::DenseMap symbolIndex; llvm::DenseMap cache; }; diff --git a/scripts/build-dev-test.sh b/scripts/build-dev-test.sh index 7cc4afcc..2c219785 100755 --- a/scripts/build-dev-test.sh +++ b/scripts/build-dev-test.sh @@ -1 +1 @@ -cmake -B build -G Ninja -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_C_COMPILER=clang -DCMAKE_BUILD_TYPE=Debug -DCLICE_ENABLE_TEST=ON -DCMAKE_CXX_FLAGS="-fno-rtti -g -O0 -fsanitize=address" \ No newline at end of file +cmake -B build -G Ninja -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_C_COMPILER=clang -DCMAKE_BUILD_TYPE=Debug -DCLICE_ENABLE_TEST=ON -DCMAKE_CXX_FLAGS="-fno-rtti -g -O0" \ No newline at end of file diff --git a/src/Index/Index.cpp b/src/Index/Index.cpp index 9a203472..64867357 100644 --- a/src/Index/Index.cpp +++ b/src/Index/Index.cpp @@ -9,7 +9,8 @@ class SymbolCollector : public clang::RecursiveASTVisitor { using Base = clang::RecursiveASTVisitor; public: - SymbolCollector(SymbolSlab& builder) : builder(builder) {} + SymbolCollector(SymbolSlab& slab, clang::ASTContext& context) : + slab(slab), context(context), srcMgr(context.getSourceManager()) {} bool TraverseDecl(clang::Decl* decl) { /// `TranslationUnitDecl` has invalid location information. @@ -18,7 +19,18 @@ public: return Base::TraverseDecl(decl); } - builder.addSymbol(decl); + if(decl->isImplicit()) { + return true; + } + + slab.addSymbol(decl); + llvm::outs() << "------------------------------------------\n"; + decl->dump(); + + llvm::SmallString<128> USR; + clang::index::generateUSRForDecl(decl, USR); + llvm::outs() << "USR: " << USR << "\n"; + // TODO: generate SymbolID for every decl. // Distinguish linkage, for no or internal linkage. // For them, relation lookup is only occurred in current TU. @@ -132,7 +144,30 @@ public: } VISIT_TYOELOC(TemplateSpecializationTypeLoc) { - auto range = loc.getTemplateNameLoc(); + auto name = loc.getTypePtr()->getTemplateName().getUnderlying(); + auto decl = name.getAsTemplateDecl(); + if(auto CTD = llvm::dyn_cast(decl)) { + auto nameLoc = loc.getTemplateNameLoc(); + auto line = srcMgr.getPresumedLineNumber(nameLoc); + auto column = srcMgr.getPresumedColumnNumber(nameLoc); + protocol::Range range = {line, + column, + line, + static_cast(column + decl->getName().size())}; + + void* ptr = CTD; + clang::ClassTemplateSpecializationDecl* decl2 = + CTD->findSpecialization(loc.getTypePtr()->template_arguments(), ptr); + auto main = decl2->getSpecializedTemplateOrPartial(); + + if(main.is()) { + auto decl3 = main.get(); + slab.addOccurrence(decl3, range, Role::ExplicitInstantiation); + } else { + auto decl3 = main.get(); + slab.addOccurrence(decl3, range, Role::ExplicitInstantiation); + } + } return true; } @@ -140,14 +175,16 @@ public: // MemberPointerTypeLoc private: - SymbolSlab& builder; + SymbolSlab& slab; + clang::ASTContext& context; + clang::SourceManager& srcMgr; }; } // namespace CSIF SymbolSlab::index(clang::ASTContext& context) { CSIF csif; - SymbolCollector collector(*this); + SymbolCollector collector(*this, context); collector.TraverseAST(context); csif.version = "0.1"; diff --git a/src/Index/SymbolSlab.cpp b/src/Index/SymbolSlab.cpp index dfb16acd..366bedc8 100644 --- a/src/Index/SymbolSlab.cpp +++ b/src/Index/SymbolSlab.cpp @@ -3,20 +3,29 @@ namespace clice { +std::size_t SymbolSlab::lookup(const clang::Decl* decl) { + auto iter = cache.find(decl); + if(iter == cache.end()) { + llvm::outs() << "SymbolSlab::lookup: decl not found\n"; + std::terminate(); + } + return iter->second; +} + SymbolSlab& SymbolSlab::addSymbol(const clang::Decl* decl) { // Generate and save USR. llvm::SmallString<128> USR; clang::index::generateUSRForDecl(decl, USR); - saver.save(USR.str()); - if(cache.contains(decl)) { - llvm::outs() << "SymbolSlab::addSymbol: decl already exists\n"; - std::terminate(); + if(!symbolIndex.contains(SymbolID::fromUSR(USR))) { + auto ID = SymbolID::fromUSR(saver.save(USR.str())); + symbols.emplace_back(ID); + cache.try_emplace(decl, symbols.size() - 1); + symbolIndex.try_emplace(ID, symbols.size() - 1); + } else { + cache.try_emplace(decl, symbolIndex[SymbolID::fromUSR(USR)]); } - auto index = symbols.size(); - symbols.emplace_back(SymbolID::fromUSR(USR.str())); - cache.try_emplace(decl, index); return *this; } diff --git a/tests/Index/Index.cpp b/tests/Index/Index.cpp index 916721d7..daa2505e 100644 --- a/tests/Index/Index.cpp +++ b/tests/Index/Index.cpp @@ -2,6 +2,7 @@ #include #include #include +#include using namespace clice; @@ -14,13 +15,17 @@ TEST(clice, Index) { "/home/ykiko/C++/clice2/build/lib/clang/20", }; const char* code = R"( -template struct X {}; +template struct X { + using type = char; +}; -template struct X {}; +template struct X { + using type = int; +}; void f() { - X y; - X x; + typename X::type y; + typename X::type x; } )"; @@ -29,5 +34,8 @@ void f() { SymbolSlab slab; auto csif = slab.index(compiler.context()); auto value = json::serialize(csif); + std::error_code EC; + llvm::raw_fd_ostream fileStream("output.json", EC); + fileStream << value << "\n"; llvm::outs() << value << "\n"; } diff --git a/tests/Source/ASTVisitor/test.cpp b/tests/Source/ASTVisitor/test.cpp index 909cbc0a..0e1bd9c1 100644 --- a/tests/Source/ASTVisitor/test.cpp +++ b/tests/Source/ASTVisitor/test.cpp @@ -1,13 +1,14 @@ -namespace { +template +struct X { + using type = char; +}; + template -struct A {}; +struct X { + using type = int; +}; -template <> -struct A {}; - -} // namespace - -int main() { - A a; - return 0; +void f() { + typename X::type y; + typename X::type x; }