forked from OSchip/llvm-project
[clang][Index] Mark references from Constructors and Destructors to class as NameReference
Summary: In current indexing logic we get references to class itself when we see a constructor/destructor which is only syntactically true. Semantically this information is not correct. This patch marks that reference as NameReference to let clients deal with it. Reviewers: akyrtzi, gribozavr, nathawes, benlangmuir Reviewed By: gribozavr, nathawes Subscribers: nathawes, arphaman, cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D58814 llvm-svn: 355668
This commit is contained in:
parent
4505c99e72
commit
e7eb27a9a0
|
@ -118,8 +118,12 @@ enum class SymbolRole : uint32_t {
|
|||
RelationContainedBy = 1 << 17,
|
||||
RelationIBTypeOf = 1 << 18,
|
||||
RelationSpecializationOf = 1 << 19,
|
||||
|
||||
// Symbol only references the name of the object as written. For example, a
|
||||
// constructor references the class declaration using that role.
|
||||
NameReference = 1 << 20,
|
||||
};
|
||||
static const unsigned SymbolRoleBitNum = 20;
|
||||
static const unsigned SymbolRoleBitNum = 21;
|
||||
typedef unsigned SymbolRoleSet;
|
||||
|
||||
/// Represents a relation to another symbol for a symbol occurrence.
|
||||
|
|
|
@ -247,7 +247,8 @@ public:
|
|||
|
||||
if (const CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(D)) {
|
||||
IndexCtx.handleReference(Ctor->getParent(), Ctor->getLocation(),
|
||||
Ctor->getParent(), Ctor->getDeclContext());
|
||||
Ctor->getParent(), Ctor->getDeclContext(),
|
||||
(unsigned)SymbolRole::NameReference);
|
||||
|
||||
// Constructor initializers.
|
||||
for (const auto *Init : Ctor->inits()) {
|
||||
|
@ -263,7 +264,8 @@ public:
|
|||
if (auto TypeNameInfo = Dtor->getNameInfo().getNamedTypeInfo()) {
|
||||
IndexCtx.handleReference(Dtor->getParent(),
|
||||
TypeNameInfo->getTypeLoc().getBeginLoc(),
|
||||
Dtor->getParent(), Dtor->getDeclContext());
|
||||
Dtor->getParent(), Dtor->getDeclContext(),
|
||||
(unsigned)SymbolRole::NameReference);
|
||||
}
|
||||
} else if (const auto *Guide = dyn_cast<CXXDeductionGuideDecl>(D)) {
|
||||
IndexCtx.handleReference(Guide->getDeducedTemplate()->getTemplatedDecl(),
|
||||
|
|
|
@ -396,6 +396,7 @@ bool index::applyForEachSymbolRoleInterruptible(SymbolRoleSet Roles,
|
|||
APPLY_FOR_ROLE(RelationContainedBy);
|
||||
APPLY_FOR_ROLE(RelationIBTypeOf);
|
||||
APPLY_FOR_ROLE(RelationSpecializationOf);
|
||||
APPLY_FOR_ROLE(NameReference);
|
||||
|
||||
#undef APPLY_FOR_ROLE
|
||||
|
||||
|
@ -438,6 +439,7 @@ void index::printSymbolRoles(SymbolRoleSet Roles, raw_ostream &OS) {
|
|||
case SymbolRole::RelationContainedBy: OS << "RelCont"; break;
|
||||
case SymbolRole::RelationIBTypeOf: OS << "RelIBType"; break;
|
||||
case SymbolRole::RelationSpecializationOf: OS << "RelSpecialization"; break;
|
||||
case SymbolRole::NameReference: OS << "NameReference"; break;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -332,6 +332,7 @@ static bool shouldReportOccurrenceForSystemDeclOnlyMode(
|
|||
case SymbolRole::RelationCalledBy:
|
||||
case SymbolRole::RelationContainedBy:
|
||||
case SymbolRole::RelationSpecializationOf:
|
||||
case SymbolRole::NameReference:
|
||||
return true;
|
||||
}
|
||||
llvm_unreachable("Unsupported SymbolRole value!");
|
||||
|
|
|
@ -5,17 +5,17 @@
|
|||
class Cls { public:
|
||||
// CHECK: [[@LINE+3]]:3 | constructor/C++ | Cls | c:@S@Cls@F@Cls#I# | __ZN3ClsC1Ei | Decl,RelChild | rel: 1
|
||||
// CHECK-NEXT: RelChild | Cls | c:@S@Cls
|
||||
// CHECK: [[@LINE+1]]:3 | class/C++ | Cls | c:@S@Cls | <no-cgname> | Ref,RelCont | rel: 1
|
||||
// CHECK: [[@LINE+1]]:3 | class/C++ | Cls | c:@S@Cls | <no-cgname> | Ref,RelCont,NameReference | rel: 1
|
||||
Cls(int x);
|
||||
// CHECK: [[@LINE+2]]:3 | constructor/cxx-copy-ctor/C++ | Cls | c:@S@Cls@F@Cls#&1$@S@Cls# | __ZN3ClsC1ERKS_ | Decl,RelChild | rel: 1
|
||||
// CHECK: [[@LINE+1]]:3 | class/C++ | Cls | c:@S@Cls | <no-cgname> | Ref,RelCont | rel: 1
|
||||
// CHECK: [[@LINE+1]]:3 | class/C++ | Cls | c:@S@Cls | <no-cgname> | Ref,RelCont,NameReference | rel: 1
|
||||
Cls(const Cls &);
|
||||
// CHECK: [[@LINE+2]]:3 | constructor/cxx-move-ctor/C++ | Cls | c:@S@Cls@F@Cls#&&$@S@Cls# | __ZN3ClsC1EOS_ | Decl,RelChild | rel: 1
|
||||
// CHECK: [[@LINE+1]]:3 | class/C++ | Cls | c:@S@Cls | <no-cgname> | Ref,RelCont | rel: 1
|
||||
// CHECK: [[@LINE+1]]:3 | class/C++ | Cls | c:@S@Cls | <no-cgname> | Ref,RelCont,NameReference | rel: 1
|
||||
Cls(Cls &&);
|
||||
|
||||
// CHECK: [[@LINE+2]]:3 | destructor/C++ | ~Cls | c:@S@Cls@F@~Cls# | __ZN3ClsD1Ev | Decl,RelChild | rel: 1
|
||||
// CHECK: [[@LINE+1]]:4 | class/C++ | Cls | c:@S@Cls | <no-cgname> | Ref,RelCont | rel: 1
|
||||
// CHECK: [[@LINE+1]]:4 | class/C++ | Cls | c:@S@Cls | <no-cgname> | Ref,RelCont,NameReference | rel: 1
|
||||
~Cls();
|
||||
};
|
||||
|
||||
|
@ -35,12 +35,12 @@ class SubCls2 : public ClsAlias {};
|
|||
Cls::Cls(int x) {}
|
||||
// CHECK: [[@LINE-1]]:6 | constructor/C++ | Cls | c:@S@Cls@F@Cls#I# | __ZN3ClsC1Ei | Def,RelChild | rel: 1
|
||||
// CHECK: [[@LINE-2]]:1 | class/C++ | Cls | c:@S@Cls | <no-cgname> | Ref,RelCont | rel: 1
|
||||
// CHECK: [[@LINE-3]]:6 | class/C++ | Cls | c:@S@Cls | <no-cgname> | Ref,RelCont | rel: 1
|
||||
// CHECK: [[@LINE-3]]:6 | class/C++ | Cls | c:@S@Cls | <no-cgname> | Ref,RelCont,NameReference | rel: 1
|
||||
|
||||
Cls::~/*a comment*/Cls() {}
|
||||
// CHECK: [[@LINE-1]]:6 | destructor/C++ | ~Cls | c:@S@Cls@F@~Cls# | __ZN3ClsD1Ev | Def,RelChild | rel: 1
|
||||
// CHECK: [[@LINE-2]]:1 | class/C++ | Cls | c:@S@Cls | <no-cgname> | Ref,RelCont | rel: 1
|
||||
// CHECK: [[@LINE-3]]:20 | class/C++ | Cls | c:@S@Cls | <no-cgname> | Ref,RelCont | rel: 1
|
||||
// CHECK: [[@LINE-3]]:20 | class/C++ | Cls | c:@S@Cls | <no-cgname> | Ref,RelCont,NameReference | rel: 1
|
||||
|
||||
template <typename TemplArg>
|
||||
class TemplCls {
|
||||
|
@ -394,7 +394,7 @@ struct DeletedMethods {
|
|||
// CHECK: [[@LINE-1]]:3 | constructor/cxx-copy-ctor/C++ | DeletedMethods | c:@S@DeletedMethods@F@DeletedMethods#&1$@S@DeletedMethods# | __ZN14DeletedMethodsC1ERKS_ | Def,RelChild | rel: 1
|
||||
// CHECK: RelChild | DeletedMethods | c:@S@DeletedMethods
|
||||
// CHECK: [[@LINE-3]]:24 | struct/C++ | DeletedMethods | c:@S@DeletedMethods | <no-cgname> | Ref,RelCont | rel: 1
|
||||
// CHECK: [[@LINE-4]]:3 | struct/C++ | DeletedMethods | c:@S@DeletedMethods | <no-cgname> | Ref,RelCont | rel: 1
|
||||
// CHECK: [[@LINE-4]]:3 | struct/C++ | DeletedMethods | c:@S@DeletedMethods | <no-cgname> | Ref,RelCont,NameReference | rel: 1
|
||||
};
|
||||
|
||||
namespace ns2 {
|
||||
|
@ -494,7 +494,7 @@ void localStructuredBindingAndRef() {
|
|||
// CHECK: [[@LINE-1]]:69 | variable/C++ | structuredBinding2 | c:@N@cpp17structuredBinding@structuredBinding2 | <no-cgname> | Ref,Read,RelCont | rel: 1
|
||||
// CHECK-NEXT: RelCont | localStructuredBindingAndRef | c:@N@cpp17structuredBinding@F@localStructuredBindingAndRef#
|
||||
// CHECK-NOT: localBinding
|
||||
// LOCAL: [[@LINE-4]]:9 | variable(local)/C++ | localBinding1 | c:index-source.cpp@25408@N@cpp17structuredBinding@F@localStructuredBindingAndRef#@localBinding1
|
||||
// LOCAL: [[@LINE-4]]:9 | variable(local)/C++ | localBinding1 | c:index-source.cpp@{{.*}}@N@cpp17structuredBinding@F@localStructuredBindingAndRef#@localBinding1
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -58,11 +58,13 @@ struct TestSymbol {
|
|||
Position WrittenPos;
|
||||
Position DeclPos;
|
||||
SymbolInfo SymInfo;
|
||||
SymbolRoleSet Roles;
|
||||
// FIXME: add more information.
|
||||
};
|
||||
|
||||
llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const TestSymbol &S) {
|
||||
return OS << S.QName << '[' << S.WrittenPos << ']' << '@' << S.DeclPos;
|
||||
return OS << S.QName << '[' << S.WrittenPos << ']' << '@' << S.DeclPos << '('
|
||||
<< static_cast<unsigned>(S.SymInfo.Kind) << ')';
|
||||
}
|
||||
|
||||
class Indexer : public IndexDataConsumer {
|
||||
|
@ -84,6 +86,7 @@ public:
|
|||
S.WrittenPos = Position::fromSourceLocation(Loc, AST->getSourceManager());
|
||||
S.DeclPos =
|
||||
Position::fromSourceLocation(D->getLocation(), AST->getSourceManager());
|
||||
S.Roles = Roles;
|
||||
Symbols.push_back(std::move(S));
|
||||
return true;
|
||||
}
|
||||
|
@ -143,6 +146,7 @@ MATCHER_P(QName, Name, "") { return arg.QName == Name; }
|
|||
MATCHER_P(WrittenAt, Pos, "") { return arg.WrittenPos == Pos; }
|
||||
MATCHER_P(DeclAt, Pos, "") { return arg.DeclPos == Pos; }
|
||||
MATCHER_P(Kind, SymKind, "") { return arg.SymInfo.Kind == SymKind; }
|
||||
MATCHER_P(HasRole, Role, "") { return arg.Roles & static_cast<unsigned>(Role); }
|
||||
|
||||
TEST(IndexTest, Simple) {
|
||||
auto Index = std::make_shared<Indexer>();
|
||||
|
@ -257,6 +261,32 @@ TEST(IndexTest, UsingDecls) {
|
|||
Contains(AllOf(QName("std::foo"), Kind(SymbolKind::Using))));
|
||||
}
|
||||
|
||||
TEST(IndexTest, Constructors) {
|
||||
std::string Code = R"cpp(
|
||||
struct Foo {
|
||||
Foo(int);
|
||||
~Foo();
|
||||
};
|
||||
)cpp";
|
||||
auto Index = std::make_shared<Indexer>();
|
||||
IndexingOptions Opts;
|
||||
tooling::runToolOnCode(new IndexAction(Index, Opts), Code);
|
||||
EXPECT_THAT(
|
||||
Index->Symbols,
|
||||
UnorderedElementsAre(
|
||||
AllOf(QName("Foo"), Kind(SymbolKind::Struct),
|
||||
WrittenAt(Position(2, 12))),
|
||||
AllOf(QName("Foo::Foo"), Kind(SymbolKind::Constructor),
|
||||
WrittenAt(Position(3, 7))),
|
||||
AllOf(QName("Foo"), Kind(SymbolKind::Struct),
|
||||
HasRole(SymbolRole::NameReference), WrittenAt(Position(3, 7))),
|
||||
AllOf(QName("Foo::~Foo"), Kind(SymbolKind::Destructor),
|
||||
WrittenAt(Position(4, 7))),
|
||||
AllOf(QName("Foo"), Kind(SymbolKind::Struct),
|
||||
HasRole(SymbolRole::NameReference),
|
||||
WrittenAt(Position(4, 8)))));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace index
|
||||
} // namespace clang
|
||||
|
|
Loading…
Reference in New Issue