aboutsummaryrefslogtreecommitdiffstats
path: root/tools/clang/codesearch/codesearch.cpp
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2026-01-21 12:21:38 +0100
committerDmitry Vyukov <dvyukov@google.com>2026-01-22 11:23:54 +0000
commit8e4581b34c9584a49bc595d65c48167b9ecbe34f (patch)
tree107cd943f49b86f1a8e4639c03c73bf80642ba57 /tools/clang/codesearch/codesearch.cpp
parent2367ed1e24f80dca97acc30309650f248a2df14b (diff)
tools/clang/codesearch: index struct references
Update #6469
Diffstat (limited to 'tools/clang/codesearch/codesearch.cpp')
-rw-r--r--tools/clang/codesearch/codesearch.cpp89
1 files changed, 77 insertions, 12 deletions
diff --git a/tools/clang/codesearch/codesearch.cpp b/tools/clang/codesearch/codesearch.cpp
index 8b096b1ab..a1174b26b 100644
--- a/tools/clang/codesearch/codesearch.cpp
+++ b/tools/clang/codesearch/codesearch.cpp
@@ -76,7 +76,12 @@ public:
bool TraverseEnumDecl(EnumDecl*);
bool TraverseTypedefDecl(TypedefDecl*);
bool TraverseCallExpr(CallExpr*);
+ bool TraverseCStyleCastExpr(CStyleCastExpr*);
+ bool TraverseVarDecl(VarDecl*);
+ bool TraverseParmVarDecl(ParmVarDecl*);
bool VisitDeclRefExpr(const DeclRefExpr*);
+ bool VisitTagType(const TagType*);
+ bool VisitTypedefType(const TypedefType*);
private:
ASTContext& Context;
@@ -84,6 +89,10 @@ private:
Output& Out;
Definition* Current = nullptr;
bool InCallee = false;
+ // If set, record references to struct types as uses.
+ SourceLocation TypeRefingLocation;
+
+ void EmitReference(SourceLocation Loc, const NamedDecl* Named, const char* EntityKind, const char* RefKind);
struct NamedDeclEmitter {
NamedDeclEmitter(Indexer* Parent, const NamedDecl* Decl, const char* Kind, const std::string& Type, bool IsStatic);
@@ -100,6 +109,13 @@ private:
using Base = RecursiveASTVisitor<Indexer>;
};
+template <typename T> struct ScopedState {
+ T* const Var;
+ T Saved;
+ ScopedState(T* Var, T ScopeValue) : Var(Var), Saved(*Var) { *Var = ScopeValue; }
+ ~ScopedState() { *Var = Saved; }
+};
+
bool Instance::handleBeginSource(CompilerInstance& CI) {
Preprocessor& PP = CI.getPreprocessor();
PP.addPPCallbacks(std::make_unique<PPCallbacksTracker>(PP, Macros));
@@ -173,27 +189,76 @@ bool Indexer::TraverseFunctionDecl(FunctionDecl* Func) {
}
bool Indexer::TraverseCallExpr(CallExpr* CE) {
- bool SavedInCallee = InCallee;
- InCallee = true;
- TraverseStmt(CE->getCallee());
- InCallee = SavedInCallee;
-
+ {
+ ScopedState<bool> Scoped(&InCallee, true);
+ TraverseStmt(CE->getCallee());
+ }
for (auto* Arg : CE->arguments())
TraverseStmt(Arg);
return true;
}
bool Indexer::VisitDeclRefExpr(const DeclRefExpr* DeclRef) {
- const auto* Func = dyn_cast<FunctionDecl>(DeclRef->getDecl());
- if (!Func || !Current)
+ if (const auto* Func = dyn_cast<FunctionDecl>(DeclRef->getDecl()))
+ EmitReference(DeclRef->getBeginLoc(), DeclRef->getDecl(), EntityKindFunction,
+ InCallee ? RefKindCall : RefKindTakesAddr);
+ return true;
+}
+
+bool Indexer::TraverseVarDecl(VarDecl* Decl) {
+ ScopedState<SourceLocation> Scoped(&TypeRefingLocation, Decl->getBeginLoc());
+ return Base::TraverseVarDecl(Decl);
+}
+
+bool Indexer::TraverseParmVarDecl(ParmVarDecl* Decl) {
+ ScopedState<SourceLocation> Scoped(&TypeRefingLocation, Decl->getBeginLoc());
+ return Base::TraverseParmVarDecl(Decl);
+}
+
+bool Indexer::TraverseCStyleCastExpr(CStyleCastExpr* Cast) {
+ ScopedState<SourceLocation> Scoped(&TypeRefingLocation, Cast->getBeginLoc());
+ return Base::TraverseCStyleCastExpr(Cast);
+}
+
+bool Indexer::VisitTagType(const TagType* T) {
+ if (TypeRefingLocation.isInvalid())
+ return true;
+ const auto* Tag = T->getAsTagDecl();
+ const char* EntityKind = nullptr;
+ if (Tag->isStruct())
+ EntityKind = EntityKindStruct;
+ else if (Tag->isUnion())
+ EntityKind = EntityKindUnion;
+ else if (Tag->isEnum())
+ EntityKind = EntityKindEnum;
+ else
return true;
+ EmitReference(TypeRefingLocation, Tag, EntityKind, RefKindUses);
+ return true;
+}
+
+bool Indexer::VisitTypedefType(const TypedefType* T) {
+ if (TypeRefingLocation.isInvalid())
+ return true;
+ EmitReference(TypeRefingLocation, T->getDecl(), EntityKindTypedef, RefKindUses);
+ // If it's a struct typedef, also note the struct use.
+ if (const auto* Tag = dyn_cast<TagType>(T->getCanonicalTypeInternal().getTypePtr()))
+ VisitTagType(Tag);
+ return true;
+}
+
+void Indexer::EmitReference(SourceLocation Loc, const NamedDecl* Named, const char* EntityKind, const char* RefKind) {
+ if (!Current || !Named || Named->getNameAsString().empty())
+ return;
+ const std::string& Name = Named->getNameAsString();
+ if (Name.empty())
+ return;
Current->Refs.push_back(Reference{
- .Kind = InCallee ? RefKindCall : RefKindTakesAddr,
- .EntityKind = EntityKindFunction,
- .Name = Func->getNameAsString(),
- .Line = static_cast<int>(SM.getExpansionLineNumber(DeclRef->getBeginLoc())),
+ .Kind = RefKind,
+ .EntityKind = EntityKind,
+ .Name = Name,
+ .Line = static_cast<int>(SM.getExpansionLineNumber(Loc)),
});
- return true;
}
bool Indexer::TraverseRecordDecl(RecordDecl* Decl) {