[clang][Index] Fix usage of IndexImplicitInstantiation
Summary:
Indexing context was skipping explicit template instantiations as well.
This patch makes sure it only skips implicit ones.
Subscribers: arphaman, jdoerfert, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D58189
llvm-svn: 354262
diff --git a/clang/unittests/Index/IndexTests.cpp b/clang/unittests/Index/IndexTests.cpp
index 2b574a5..61c969f 100644
--- a/clang/unittests/Index/IndexTests.cpp
+++ b/clang/unittests/Index/IndexTests.cpp
@@ -7,7 +7,10 @@
//===----------------------------------------------------------------------===//
#include "clang/AST/ASTConsumer.h"
+#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/SourceManager.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/FrontendAction.h"
#include "clang/Index/IndexDataConsumer.h"
@@ -23,27 +26,62 @@
namespace clang {
namespace index {
+namespace {
+struct Position {
+ size_t Line = 0;
+ size_t Column = 0;
+
+ Position(size_t Line = 0, size_t Column = 0) : Line(Line), Column(Column) {}
+
+ static Position fromSourceLocation(SourceLocation Loc,
+ const SourceManager &SM) {
+ FileID FID;
+ unsigned Offset;
+ std::tie(FID, Offset) = SM.getDecomposedSpellingLoc(Loc);
+ Position P;
+ P.Line = SM.getLineNumber(FID, Offset);
+ P.Column = SM.getColumnNumber(FID, Offset);
+ return P;
+ }
+};
+
+bool operator==(const Position &LHS, const Position &RHS) {
+ return std::tie(LHS.Line, LHS.Column) == std::tie(RHS.Line, RHS.Column);
+}
+
+llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const Position &Pos) {
+ return OS << Pos.Line << ':' << Pos.Column;
+}
struct TestSymbol {
std::string QName;
+ Position WrittenPos;
+ Position DeclPos;
// FIXME: add more information.
};
llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const TestSymbol &S) {
- return OS << S.QName;
+ return OS << S.QName << '[' << S.WrittenPos << ']' << '@' << S.DeclPos;
}
-namespace {
class Indexer : public IndexDataConsumer {
public:
+ void initialize(ASTContext &Ctx) override {
+ AST = &Ctx;
+ IndexDataConsumer::initialize(Ctx);
+ }
+
bool handleDeclOccurence(const Decl *D, SymbolRoleSet Roles,
- ArrayRef<SymbolRelation>, SourceLocation,
+ ArrayRef<SymbolRelation>, SourceLocation Loc,
ASTNodeInfo) override {
const auto *ND = llvm::dyn_cast<NamedDecl>(D);
if (!ND)
return true;
TestSymbol S;
S.QName = ND->getQualifiedNameAsString();
+ S.WrittenPos = Position::fromSourceLocation(Loc, AST->getSourceManager());
+ S.DeclPos =
+ Position::fromSourceLocation(D->getLocation(), AST->getSourceManager());
Symbols.push_back(std::move(S));
return true;
}
@@ -57,6 +95,7 @@
}
std::vector<TestSymbol> Symbols;
+ const ASTContext *AST = nullptr;
};
class IndexAction : public ASTFrontendAction {
@@ -93,11 +132,14 @@
IndexingOptions Opts;
};
+using testing::AllOf;
using testing::Contains;
using testing::Not;
using testing::UnorderedElementsAre;
MATCHER_P(QName, Name, "") { return arg.QName == Name; }
+MATCHER_P(WrittenAt, Pos, "") { return arg.WrittenPos == Pos; }
+MATCHER_P(DeclAt, Pos, "") { return arg.DeclPos == Pos; }
TEST(IndexTest, Simple) {
auto Index = std::make_shared<Indexer>();
@@ -134,6 +176,46 @@
EXPECT_THAT(Index->Symbols, Not(Contains(QName("bar"))));
}
+TEST(IndexTest, IndexExplicitTemplateInstantiation) {
+ std::string Code = R"cpp(
+ template <typename T>
+ struct Foo { void bar() {} };
+ template <>
+ struct Foo<int> { void bar() {} };
+ void foo() {
+ Foo<char> abc;
+ Foo<int> b;
+ }
+ )cpp";
+ auto Index = std::make_shared<Indexer>();
+ IndexingOptions Opts;
+ tooling::runToolOnCode(new IndexAction(Index, Opts), Code);
+ EXPECT_THAT(Index->Symbols,
+ AllOf(Contains(AllOf(QName("Foo"), WrittenAt(Position(8, 7)),
+ DeclAt(Position(5, 12)))),
+ Contains(AllOf(QName("Foo"), WrittenAt(Position(7, 7)),
+ DeclAt(Position(3, 12))))));
+}
+
+TEST(IndexTest, IndexTemplateInstantiationPartial) {
+ std::string Code = R"cpp(
+ template <typename T1, typename T2>
+ struct Foo { void bar() {} };
+ template <typename T>
+ struct Foo<T, int> { void bar() {} };
+ void foo() {
+ Foo<char, char> abc;
+ Foo<int, int> b;
+ }
+ )cpp";
+ auto Index = std::make_shared<Indexer>();
+ IndexingOptions Opts;
+ tooling::runToolOnCode(new IndexAction(Index, Opts), Code);
+ EXPECT_THAT(Index->Symbols,
+ Contains(AllOf(QName("Foo"), WrittenAt(Position(8, 7)),
+ DeclAt(Position(5, 12)))));
+}
+
} // namespace
} // namespace index
} // namespace clang