123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487 |
- //===- IndexBody.cpp - Indexing statements --------------------------------===//
- //
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
- // See https://llvm.org/LICENSE.txt for license information.
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- //
- //===----------------------------------------------------------------------===//
- #include "IndexingContext.h"
- #include "clang/AST/RecursiveASTVisitor.h"
- #include "clang/AST/ASTLambda.h"
- using namespace clang;
- using namespace clang::index;
- namespace {
- class BodyIndexer : public RecursiveASTVisitor<BodyIndexer> {
- IndexingContext &IndexCtx;
- const NamedDecl *Parent;
- const DeclContext *ParentDC;
- SmallVector<Stmt*, 16> StmtStack;
- typedef RecursiveASTVisitor<BodyIndexer> base;
- Stmt *getParentStmt() const {
- return StmtStack.size() < 2 ? nullptr : StmtStack.end()[-2];
- }
- public:
- BodyIndexer(IndexingContext &indexCtx,
- const NamedDecl *Parent, const DeclContext *DC)
- : IndexCtx(indexCtx), Parent(Parent), ParentDC(DC) { }
- bool shouldWalkTypesOfTypeLocs() const { return false; }
- bool dataTraverseStmtPre(Stmt *S) {
- StmtStack.push_back(S);
- return true;
- }
- bool dataTraverseStmtPost(Stmt *S) {
- assert(StmtStack.back() == S);
- StmtStack.pop_back();
- return true;
- }
- bool TraverseTypeLoc(TypeLoc TL) {
- IndexCtx.indexTypeLoc(TL, Parent, ParentDC);
- return true;
- }
- bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) {
- IndexCtx.indexNestedNameSpecifierLoc(NNS, Parent, ParentDC);
- return true;
- }
- SymbolRoleSet getRolesForRef(const Expr *E,
- SmallVectorImpl<SymbolRelation> &Relations) {
- SymbolRoleSet Roles{};
- assert(!StmtStack.empty() && E == StmtStack.back());
- if (StmtStack.size() == 1)
- return Roles;
- auto It = StmtStack.end()-2;
- while (isa<CastExpr>(*It) || isa<ParenExpr>(*It)) {
- if (auto ICE = dyn_cast<ImplicitCastExpr>(*It)) {
- if (ICE->getCastKind() == CK_LValueToRValue)
- Roles |= (unsigned)(unsigned)SymbolRole::Read;
- }
- if (It == StmtStack.begin())
- break;
- --It;
- }
- const Stmt *Parent = *It;
- if (auto BO = dyn_cast<BinaryOperator>(Parent)) {
- if (BO->getOpcode() == BO_Assign && BO->getLHS()->IgnoreParenCasts() == E)
- Roles |= (unsigned)SymbolRole::Write;
- } else if (auto UO = dyn_cast<UnaryOperator>(Parent)) {
- if (UO->isIncrementDecrementOp()) {
- Roles |= (unsigned)SymbolRole::Read;
- Roles |= (unsigned)SymbolRole::Write;
- } else if (UO->getOpcode() == UO_AddrOf) {
- Roles |= (unsigned)SymbolRole::AddressOf;
- }
- } else if (auto CA = dyn_cast<CompoundAssignOperator>(Parent)) {
- if (CA->getLHS()->IgnoreParenCasts() == E) {
- Roles |= (unsigned)SymbolRole::Read;
- Roles |= (unsigned)SymbolRole::Write;
- }
- } else if (auto CE = dyn_cast<CallExpr>(Parent)) {
- if (CE->getCallee()->IgnoreParenCasts() == E) {
- addCallRole(Roles, Relations);
- if (auto *ME = dyn_cast<MemberExpr>(E)) {
- if (auto *CXXMD = dyn_cast_or_null<CXXMethodDecl>(ME->getMemberDecl()))
- if (CXXMD->isVirtual() && !ME->hasQualifier()) {
- Roles |= (unsigned)SymbolRole::Dynamic;
- auto BaseTy = ME->getBase()->IgnoreImpCasts()->getType();
- if (!BaseTy.isNull())
- if (auto *CXXRD = BaseTy->getPointeeCXXRecordDecl())
- Relations.emplace_back((unsigned)SymbolRole::RelationReceivedBy,
- CXXRD);
- }
- }
- } else if (auto CXXOp = dyn_cast<CXXOperatorCallExpr>(CE)) {
- if (CXXOp->getNumArgs() > 0 && CXXOp->getArg(0)->IgnoreParenCasts() == E) {
- OverloadedOperatorKind Op = CXXOp->getOperator();
- if (Op == OO_Equal) {
- Roles |= (unsigned)SymbolRole::Write;
- } else if ((Op >= OO_PlusEqual && Op <= OO_PipeEqual) ||
- Op == OO_LessLessEqual || Op == OO_GreaterGreaterEqual ||
- Op == OO_PlusPlus || Op == OO_MinusMinus) {
- Roles |= (unsigned)SymbolRole::Read;
- Roles |= (unsigned)SymbolRole::Write;
- } else if (Op == OO_Amp) {
- Roles |= (unsigned)SymbolRole::AddressOf;
- }
- }
- }
- }
- return Roles;
- }
- void addCallRole(SymbolRoleSet &Roles,
- SmallVectorImpl<SymbolRelation> &Relations) {
- Roles |= (unsigned)SymbolRole::Call;
- if (auto *FD = dyn_cast<FunctionDecl>(ParentDC))
- Relations.emplace_back((unsigned)SymbolRole::RelationCalledBy, FD);
- else if (auto *MD = dyn_cast<ObjCMethodDecl>(ParentDC))
- Relations.emplace_back((unsigned)SymbolRole::RelationCalledBy, MD);
- }
- bool VisitDeclRefExpr(DeclRefExpr *E) {
- SmallVector<SymbolRelation, 4> Relations;
- SymbolRoleSet Roles = getRolesForRef(E, Relations);
- return IndexCtx.handleReference(E->getDecl(), E->getLocation(),
- Parent, ParentDC, Roles, Relations, E);
- }
- bool VisitMemberExpr(MemberExpr *E) {
- SourceLocation Loc = E->getMemberLoc();
- if (Loc.isInvalid())
- Loc = E->getBeginLoc();
- SmallVector<SymbolRelation, 4> Relations;
- SymbolRoleSet Roles = getRolesForRef(E, Relations);
- return IndexCtx.handleReference(E->getMemberDecl(), Loc,
- 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);
- // FIXME: Improve overload handling.
- if (Symbols.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);
- }
- bool VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E) {
- const DeclarationNameInfo &Info = E->getMemberNameInfo();
- return indexDependentReference(
- E, E->getBaseType().getTypePtrOrNull(), Info,
- [](const NamedDecl *D) { return D->isCXXInstanceMember(); });
- }
- 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(); });
- }
- bool VisitDesignatedInitExpr(DesignatedInitExpr *E) {
- for (DesignatedInitExpr::Designator &D : llvm::reverse(E->designators())) {
- if (D.isFieldDesignator() && D.getField())
- return IndexCtx.handleReference(D.getField(), D.getFieldLoc(), Parent,
- ParentDC, SymbolRoleSet(), {}, E);
- }
- return true;
- }
- bool VisitObjCIvarRefExpr(ObjCIvarRefExpr *E) {
- SmallVector<SymbolRelation, 4> Relations;
- SymbolRoleSet Roles = getRolesForRef(E, Relations);
- return IndexCtx.handleReference(E->getDecl(), E->getLocation(),
- Parent, ParentDC, Roles, Relations, E);
- }
- bool VisitObjCMessageExpr(ObjCMessageExpr *E) {
- auto isDynamic = [](const ObjCMessageExpr *MsgE)->bool {
- if (MsgE->getReceiverKind() != ObjCMessageExpr::Instance)
- return false;
- if (auto *RecE = dyn_cast<ObjCMessageExpr>(
- MsgE->getInstanceReceiver()->IgnoreParenCasts())) {
- if (RecE->getMethodFamily() == OMF_alloc)
- return false;
- }
- return true;
- };
- if (ObjCMethodDecl *MD = E->getMethodDecl()) {
- SymbolRoleSet Roles{};
- SmallVector<SymbolRelation, 2> Relations;
- addCallRole(Roles, Relations);
- Stmt *Containing = getParentStmt();
- auto IsImplicitProperty = [](const PseudoObjectExpr *POE) -> bool {
- const auto *E = POE->getSyntacticForm();
- if (const auto *BinOp = dyn_cast<BinaryOperator>(E))
- E = BinOp->getLHS();
- const auto *PRE = dyn_cast<ObjCPropertyRefExpr>(E);
- if (!PRE)
- return false;
- if (PRE->isExplicitProperty())
- return false;
- if (const ObjCMethodDecl *Getter = PRE->getImplicitPropertyGetter()) {
- // Class properties that are explicitly defined using @property
- // declarations are represented implicitly as there is no ivar for
- // class properties.
- if (Getter->isClassMethod() &&
- Getter->getCanonicalDecl()->findPropertyDecl())
- return false;
- }
- return true;
- };
- bool IsPropCall = Containing && isa<PseudoObjectExpr>(Containing);
- // Implicit property message sends are not 'implicit'.
- if ((E->isImplicit() || IsPropCall) &&
- !(IsPropCall &&
- IsImplicitProperty(cast<PseudoObjectExpr>(Containing))))
- Roles |= (unsigned)SymbolRole::Implicit;
- if (isDynamic(E)) {
- Roles |= (unsigned)SymbolRole::Dynamic;
- auto addReceivers = [&](const ObjCObjectType *Ty) {
- if (!Ty)
- return;
- if (const auto *clsD = Ty->getInterface()) {
- Relations.emplace_back((unsigned)SymbolRole::RelationReceivedBy,
- clsD);
- }
- for (const auto *protD : Ty->quals()) {
- Relations.emplace_back((unsigned)SymbolRole::RelationReceivedBy,
- protD);
- }
- };
- QualType recT = E->getReceiverType();
- if (const auto *Ptr = recT->getAs<ObjCObjectPointerType>())
- addReceivers(Ptr->getObjectType());
- else
- addReceivers(recT->getAs<ObjCObjectType>());
- }
- return IndexCtx.handleReference(MD, E->getSelectorStartLoc(),
- Parent, ParentDC, Roles, Relations, E);
- }
- return true;
- }
- bool VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E) {
- if (E->isExplicitProperty()) {
- SmallVector<SymbolRelation, 2> Relations;
- SymbolRoleSet Roles = getRolesForRef(E, Relations);
- return IndexCtx.handleReference(E->getExplicitProperty(), E->getLocation(),
- Parent, ParentDC, Roles, Relations, E);
- } else if (const ObjCMethodDecl *Getter = E->getImplicitPropertyGetter()) {
- // Class properties that are explicitly defined using @property
- // declarations are represented implicitly as there is no ivar for class
- // properties.
- if (Getter->isClassMethod()) {
- if (const auto *PD = Getter->getCanonicalDecl()->findPropertyDecl()) {
- SmallVector<SymbolRelation, 2> Relations;
- SymbolRoleSet Roles = getRolesForRef(E, Relations);
- return IndexCtx.handleReference(PD, E->getLocation(), Parent,
- ParentDC, Roles, Relations, E);
- }
- }
- }
- // No need to do a handleReference for the objc method, because there will
- // be a message expr as part of PseudoObjectExpr.
- return true;
- }
- bool VisitMSPropertyRefExpr(MSPropertyRefExpr *E) {
- return IndexCtx.handleReference(E->getPropertyDecl(), E->getMemberLoc(),
- Parent, ParentDC, SymbolRoleSet(), {}, E);
- }
- bool VisitObjCProtocolExpr(ObjCProtocolExpr *E) {
- return IndexCtx.handleReference(E->getProtocol(), E->getProtocolIdLoc(),
- Parent, ParentDC, SymbolRoleSet(), {}, E);
- }
- bool passObjCLiteralMethodCall(const ObjCMethodDecl *MD, const Expr *E) {
- SymbolRoleSet Roles{};
- SmallVector<SymbolRelation, 2> Relations;
- addCallRole(Roles, Relations);
- Roles |= (unsigned)SymbolRole::Implicit;
- return IndexCtx.handleReference(MD, E->getBeginLoc(), Parent, ParentDC,
- Roles, Relations, E);
- }
- bool VisitObjCBoxedExpr(ObjCBoxedExpr *E) {
- if (ObjCMethodDecl *MD = E->getBoxingMethod()) {
- return passObjCLiteralMethodCall(MD, E);
- }
- return true;
- }
- bool VisitObjCDictionaryLiteral(ObjCDictionaryLiteral *E) {
- if (ObjCMethodDecl *MD = E->getDictWithObjectsMethod()) {
- return passObjCLiteralMethodCall(MD, E);
- }
- return true;
- }
- bool VisitObjCArrayLiteral(ObjCArrayLiteral *E) {
- if (ObjCMethodDecl *MD = E->getArrayWithObjectsMethod()) {
- return passObjCLiteralMethodCall(MD, E);
- }
- return true;
- }
- bool VisitCXXConstructExpr(CXXConstructExpr *E) {
- SymbolRoleSet Roles{};
- SmallVector<SymbolRelation, 2> Relations;
- addCallRole(Roles, Relations);
- return IndexCtx.handleReference(E->getConstructor(), E->getLocation(),
- Parent, ParentDC, Roles, Relations, E);
- }
- bool TraverseCXXOperatorCallExpr(CXXOperatorCallExpr *E,
- DataRecursionQueue *Q = nullptr) {
- if (E->getOperatorLoc().isInvalid())
- return true; // implicit.
- return base::TraverseCXXOperatorCallExpr(E, Q);
- }
- bool VisitDeclStmt(DeclStmt *S) {
- if (IndexCtx.shouldIndexFunctionLocalSymbols()) {
- IndexCtx.indexDeclGroupRef(S->getDeclGroup());
- return true;
- }
- DeclGroupRef DG = S->getDeclGroup();
- for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I) {
- const Decl *D = *I;
- if (!D)
- continue;
- if (!isFunctionLocalSymbol(D))
- IndexCtx.indexTopLevelDecl(D);
- }
- return true;
- }
- bool TraverseLambdaCapture(LambdaExpr *LE, const LambdaCapture *C,
- Expr *Init) {
- if (C->capturesThis() || C->capturesVLAType())
- return true;
- if (!base::TraverseStmt(Init))
- return false;
- if (C->capturesVariable() && IndexCtx.shouldIndexFunctionLocalSymbols())
- return IndexCtx.handleReference(C->getCapturedVar(), C->getLocation(),
- Parent, ParentDC, SymbolRoleSet());
- return true;
- }
- // RecursiveASTVisitor visits both syntactic and semantic forms, duplicating
- // the things that we visit. Make sure to only visit the semantic form.
- // Also visit things that are in the syntactic form but not the semantic one,
- // for example the indices in DesignatedInitExprs.
- bool TraverseInitListExpr(InitListExpr *S, DataRecursionQueue *Q = nullptr) {
- auto visitForm = [&](InitListExpr *Form) {
- for (Stmt *SubStmt : Form->children()) {
- if (!TraverseStmt(SubStmt, Q))
- return false;
- }
- return true;
- };
- auto visitSyntacticDesignatedInitExpr = [&](DesignatedInitExpr *E) -> bool {
- for (DesignatedInitExpr::Designator &D : llvm::reverse(E->designators())) {
- if (D.isFieldDesignator() && D.getField())
- return IndexCtx.handleReference(D.getField(), D.getFieldLoc(),
- Parent, ParentDC, SymbolRoleSet(),
- {}, E);
- }
- return true;
- };
- InitListExpr *SemaForm = S->isSemanticForm() ? S : S->getSemanticForm();
- InitListExpr *SyntaxForm = S->isSemanticForm() ? S->getSyntacticForm() : S;
- if (SemaForm) {
- // Visit things present in syntactic form but not the semantic form.
- if (SyntaxForm) {
- for (Expr *init : SyntaxForm->inits()) {
- if (auto *DIE = dyn_cast<DesignatedInitExpr>(init))
- visitSyntacticDesignatedInitExpr(DIE);
- }
- }
- return visitForm(SemaForm);
- }
- // No semantic, try the syntactic.
- if (SyntaxForm) {
- return visitForm(SyntaxForm);
- }
- return true;
- }
- bool VisitOffsetOfExpr(OffsetOfExpr *S) {
- for (unsigned I = 0, E = S->getNumComponents(); I != E; ++I) {
- const OffsetOfNode &Component = S->getComponent(I);
- if (Component.getKind() == OffsetOfNode::Field)
- IndexCtx.handleReference(Component.getField(), Component.getEndLoc(),
- Parent, ParentDC, SymbolRoleSet(), {});
- // FIXME: Try to resolve dependent field references.
- }
- return true;
- }
- bool VisitParmVarDecl(ParmVarDecl* D) {
- // Index the parameters of lambda expression.
- if (IndexCtx.shouldIndexFunctionLocalSymbols()) {
- const auto *DC = D->getDeclContext();
- if (DC && isLambdaCallOperator(DC))
- IndexCtx.handleDecl(D);
- }
- return true;
- }
- bool VisitUnresolvedLookupExpr(UnresolvedLookupExpr *E) {
- SmallVector<SymbolRelation, 4> Relations;
- SymbolRoleSet Roles = getRolesForRef(E, Relations);
- for (auto *D : E->decls())
- IndexCtx.handleReference(D, E->getNameLoc(), Parent, ParentDC, Roles,
- Relations, E);
- return true;
- }
- };
- } // anonymous namespace
- void IndexingContext::indexBody(const Stmt *S, const NamedDecl *Parent,
- const DeclContext *DC) {
- if (!S)
- return;
- if (!DC)
- DC = Parent->getLexicalDeclContext();
- BodyIndexer(*this, Parent, DC).TraverseStmt(const_cast<Stmt*>(S));
- }
|