[clang][Index] Use HeuristicResolver in libIndex (#125153)
The uses replace hand-rolled code that did a subset of what HeuristicResolver does.
This commit is contained in:
@@ -23,6 +23,7 @@ add_clang_library(clangIndex
|
||||
clangFormat
|
||||
clangFrontend
|
||||
clangLex
|
||||
clangSema
|
||||
clangSerialization
|
||||
clangToolingCore
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include "clang/AST/ExprConcepts.h"
|
||||
#include "clang/AST/RecursiveASTVisitor.h"
|
||||
#include "clang/AST/Type.h"
|
||||
#include "clang/Sema/HeuristicResolver.h"
|
||||
|
||||
using namespace clang;
|
||||
using namespace clang::index;
|
||||
@@ -168,51 +169,31 @@ public:
|
||||
Parent, ParentDC, Roles, Relations, E);
|
||||
}
|
||||
|
||||
bool indexDependentReference(
|
||||
const Expr *E, const Type *T, const DeclarationNameInfo &NameInfo,
|
||||
llvm::function_ref<bool(const NamedDecl *ND)> Filter) {
|
||||
if (!T)
|
||||
return true;
|
||||
const TemplateSpecializationType *TST =
|
||||
T->getAs<TemplateSpecializationType>();
|
||||
if (!TST)
|
||||
return true;
|
||||
TemplateName TN = TST->getTemplateName();
|
||||
const ClassTemplateDecl *TD =
|
||||
dyn_cast_or_null<ClassTemplateDecl>(TN.getAsTemplateDecl());
|
||||
if (!TD)
|
||||
return true;
|
||||
CXXRecordDecl *RD = TD->getTemplatedDecl();
|
||||
if (!RD->hasDefinition())
|
||||
return true;
|
||||
RD = RD->getDefinition();
|
||||
std::vector<const NamedDecl *> Symbols =
|
||||
RD->lookupDependentName(NameInfo.getName(), Filter);
|
||||
bool indexDependentReference(const Expr *E, SourceLocation Loc,
|
||||
std::vector<const NamedDecl *> TargetSymbols) {
|
||||
// FIXME: Improve overload handling.
|
||||
if (Symbols.size() != 1)
|
||||
if (TargetSymbols.size() != 1)
|
||||
return true;
|
||||
SourceLocation Loc = NameInfo.getLoc();
|
||||
if (Loc.isInvalid())
|
||||
Loc = E->getBeginLoc();
|
||||
SmallVector<SymbolRelation, 4> Relations;
|
||||
SymbolRoleSet Roles = getRolesForRef(E, Relations);
|
||||
return IndexCtx.handleReference(Symbols[0], Loc, Parent, ParentDC, Roles,
|
||||
Relations, E);
|
||||
return IndexCtx.handleReference(TargetSymbols[0], Loc, Parent, ParentDC,
|
||||
Roles, Relations, E);
|
||||
}
|
||||
|
||||
bool VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E) {
|
||||
const DeclarationNameInfo &Info = E->getMemberNameInfo();
|
||||
return indexDependentReference(
|
||||
E, E->getBaseType().getTypePtrOrNull(), Info,
|
||||
[](const NamedDecl *D) { return D->isCXXInstanceMember(); });
|
||||
auto *Resolver = IndexCtx.getResolver();
|
||||
assert(Resolver);
|
||||
return indexDependentReference(E, E->getMemberNameInfo().getLoc(),
|
||||
Resolver->resolveMemberExpr(E));
|
||||
}
|
||||
|
||||
bool VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E) {
|
||||
const DeclarationNameInfo &Info = E->getNameInfo();
|
||||
const NestedNameSpecifier *NNS = E->getQualifier();
|
||||
return indexDependentReference(
|
||||
E, NNS->getAsType(), Info,
|
||||
[](const NamedDecl *D) { return !D->isCXXInstanceMember(); });
|
||||
auto *Resolver = IndexCtx.getResolver();
|
||||
assert(Resolver);
|
||||
return indexDependentReference(E, E->getNameInfo().getLoc(),
|
||||
Resolver->resolveDeclRefExpr(E));
|
||||
}
|
||||
|
||||
bool VisitDesignatedInitExpr(DesignatedInitExpr *E) {
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include "clang/Basic/SourceLocation.h"
|
||||
#include "clang/Basic/SourceManager.h"
|
||||
#include "clang/Index/IndexDataConsumer.h"
|
||||
#include "clang/Sema/HeuristicResolver.h"
|
||||
|
||||
using namespace clang;
|
||||
using namespace index;
|
||||
@@ -25,6 +26,17 @@ static bool isGeneratedDecl(const Decl *D) {
|
||||
return false;
|
||||
}
|
||||
|
||||
IndexingContext::IndexingContext(IndexingOptions IndexOpts,
|
||||
IndexDataConsumer &DataConsumer)
|
||||
: IndexOpts(IndexOpts), DataConsumer(DataConsumer) {}
|
||||
|
||||
IndexingContext::~IndexingContext() = default;
|
||||
|
||||
void IndexingContext::setASTContext(ASTContext &ctx) {
|
||||
Ctx = &ctx;
|
||||
Resolver = Ctx ? std::make_unique<HeuristicResolver>(*Ctx) : nullptr;
|
||||
}
|
||||
|
||||
bool IndexingContext::shouldIndex(const Decl *D) {
|
||||
return !isGeneratedDecl(D);
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ namespace clang {
|
||||
class Decl;
|
||||
class DeclGroupRef;
|
||||
class ImportDecl;
|
||||
class HeuristicResolver;
|
||||
class TagDecl;
|
||||
class TypeSourceInfo;
|
||||
class NamedDecl;
|
||||
@@ -39,15 +40,18 @@ class IndexingContext {
|
||||
IndexingOptions IndexOpts;
|
||||
IndexDataConsumer &DataConsumer;
|
||||
ASTContext *Ctx = nullptr;
|
||||
std::unique_ptr<HeuristicResolver> Resolver;
|
||||
|
||||
public:
|
||||
IndexingContext(IndexingOptions IndexOpts, IndexDataConsumer &DataConsumer)
|
||||
: IndexOpts(IndexOpts), DataConsumer(DataConsumer) {}
|
||||
IndexingContext(IndexingOptions IndexOpts, IndexDataConsumer &DataConsumer);
|
||||
~IndexingContext();
|
||||
|
||||
const IndexingOptions &getIndexOpts() const { return IndexOpts; }
|
||||
IndexDataConsumer &getDataConsumer() { return DataConsumer; }
|
||||
|
||||
void setASTContext(ASTContext &ctx) { Ctx = &ctx; }
|
||||
void setASTContext(ASTContext &ctx);
|
||||
|
||||
HeuristicResolver *getResolver() const { return Resolver.get(); }
|
||||
|
||||
bool shouldIndex(const Decl *D);
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
int invalid;
|
||||
|
||||
class Base {
|
||||
void baseFunction();
|
||||
void baseFunction() const;
|
||||
|
||||
int baseField;
|
||||
|
||||
@@ -13,7 +13,7 @@ class Base {
|
||||
template<typename T>
|
||||
class BaseTemplate {
|
||||
public:
|
||||
T baseTemplateFunction();
|
||||
T baseTemplateFunction() const;
|
||||
|
||||
T baseTemplateField;
|
||||
|
||||
@@ -25,7 +25,7 @@ class TemplateClass: public Base , public BaseTemplate<T> {
|
||||
public:
|
||||
~TemplateClass();
|
||||
|
||||
T function() { }
|
||||
T function() const { }
|
||||
|
||||
static void staticFunction() { }
|
||||
|
||||
@@ -48,27 +48,27 @@ template<typename T, typename S>
|
||||
void indexSimpleDependentDeclarations(const TemplateClass<T, S> &object) {
|
||||
// Valid instance members:
|
||||
object.function();
|
||||
// CHECK: [[@LINE-1]]:10 | instance-method/C++ | function | c:@ST>2#T#T@TemplateClass@F@function# | <no-cgname> | Ref,Call,RelCall,RelCont | rel: 1
|
||||
// CHECK: [[@LINE-1]]:10 | instance-method/C++ | function | c:@ST>2#T#T@TemplateClass@F@function#1 | <no-cgname> | Ref,Call,RelCall,RelCont | rel: 1
|
||||
object.field;
|
||||
// CHECK: [[@LINE-1]]:10 | field/C++ | field | c:@ST>2#T#T@TemplateClass@FI@field | <no-cgname> | Ref,RelCont | rel: 1
|
||||
object.baseFunction();
|
||||
// CHECK: [[@LINE-1]]:10 | instance-method/C++ | baseFunction | c:@S@Base@F@baseFunction# | __ZN4Base12baseFunctionEv | Ref,Call,RelCall,RelCont | rel: 1
|
||||
// CHECK: [[@LINE-1]]:10 | instance-method/C++ | baseFunction | c:@S@Base@F@baseFunction#1 | __ZNK4Base12baseFunctionEv | Ref,Call,RelCall,RelCont | rel: 1
|
||||
object.baseField;
|
||||
// CHECK: [[@LINE-1]]:10 | field/C++ | baseField | c:@S@Base@FI@baseField | <no-cgname> | Ref,RelCont | rel: 1
|
||||
object.baseTemplateFunction();
|
||||
// CHECK: [[@LINE-1]]:10 | instance-method/C++ | baseTemplateFunction | c:@ST>1#T@BaseTemplate@F@baseTemplateFunction# | <no-cgname> | Ref,Call,RelCall,RelCont | rel: 1
|
||||
// CHECK: [[@LINE-1]]:10 | instance-method/C++ | baseTemplateFunction | c:@ST>1#T@BaseTemplate@F@baseTemplateFunction#1 | <no-cgname> | Ref,Call,RelCall,RelCont | rel: 1
|
||||
object.baseTemplateField;
|
||||
// CHECK: [[@LINE-1]]:10 | field/C++ | baseTemplateField | c:@ST>1#T@BaseTemplate@FI@baseTemplateField | <no-cgname> | Ref,RelCont | rel: 1
|
||||
|
||||
// Invalid instance members:
|
||||
// Static members (these are still valid to access via an instance):
|
||||
object.variable;
|
||||
// CHECK-NOT: [[@LINE-1]]:10
|
||||
// CHECK: [[@LINE-1]]:10 | static-property/C++ | variable | c:@ST>2#T#T@TemplateClass@variable | __ZN13TemplateClass8variableE | Ref,RelCont | rel: 1
|
||||
object.staticFunction();
|
||||
// CHECK-NOT: [[@LINE-1]]:10
|
||||
// CHECK: [[@LINE-1]]:10 | static-method/C++ | staticFunction | c:@ST>2#T#T@TemplateClass@F@staticFunction#S | <no-cgname> | Ref,Call,RelCall,RelCont | rel: 1
|
||||
object.Struct;
|
||||
// CHECK-NOT: [[@LINE-1]]:10
|
||||
// CHECK: [[@LINE-1]]:10 | struct/C | Struct | c:@ST>2#T#T@TemplateClass@S@Struct | <no-cgname> | Ref,RelCont | rel: 1
|
||||
object.EnumValue;
|
||||
// CHECK-NOT: [[@LINE-1]]:10
|
||||
// CHECK: [[@LINE-1]]:10 | enumerator/C | EnumValue | c:@ST>2#T#T@TemplateClass@E@Enum@EnumValue | <no-cgname> | Ref,RelCont | rel: 1
|
||||
|
||||
// Valid static members:
|
||||
TemplateClass<T, S>::staticFunction();
|
||||
|
||||
Reference in New Issue
Block a user