Skip to content

Commit

Permalink
[clang][Index] Use HeuristicResolver in libIndex (#125153)
Browse files Browse the repository at this point in the history
The uses replace hand-rolled code that did a subset of what
HeuristicResolver does.
  • Loading branch information
HighCommander4 authored Feb 18, 2025
1 parent 0b719d3 commit d09cce1
Show file tree
Hide file tree
Showing 5 changed files with 45 additions and 47 deletions.
1 change: 1 addition & 0 deletions clang/lib/Index/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ add_clang_library(clangIndex
clangFormat
clangFrontend
clangLex
clangSema
clangSerialization
clangToolingCore

Expand Down
47 changes: 14 additions & 33 deletions clang/lib/Index/IndexBody.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -168,51 +169,31 @@ class BodyIndexer : public RecursiveASTVisitor<BodyIndexer> {
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) {
Expand Down
12 changes: 12 additions & 0 deletions clang/lib/Index/IndexingContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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);
}
Expand Down
10 changes: 7 additions & 3 deletions clang/lib/Index/IndexingContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ namespace clang {
class Decl;
class DeclGroupRef;
class ImportDecl;
class HeuristicResolver;
class TagDecl;
class TypeSourceInfo;
class NamedDecl;
Expand All @@ -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);

Expand Down
22 changes: 11 additions & 11 deletions clang/test/Index/Core/index-dependent-source.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
int invalid;

class Base {
void baseFunction();
void baseFunction() const;

int baseField;

Expand All @@ -13,7 +13,7 @@ class Base {
template<typename T>
class BaseTemplate {
public:
T baseTemplateFunction();
T baseTemplateFunction() const;

T baseTemplateField;

Expand All @@ -25,7 +25,7 @@ class TemplateClass: public Base , public BaseTemplate<T> {
public:
~TemplateClass();

T function() { }
T function() const { }

static void staticFunction() { }

Expand All @@ -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();
Expand Down

0 comments on commit d09cce1

Please sign in to comment.