Coverage Report

Created: 2023-09-21 18:56

/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/lib/Index/IndexBody.cpp
Line
Count
Source (jump to first uncovered line)
1
//===- IndexBody.cpp - Indexing statements --------------------------------===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
9
#include "IndexingContext.h"
10
#include "clang/AST/ASTConcept.h"
11
#include "clang/AST/ASTLambda.h"
12
#include "clang/AST/DeclCXX.h"
13
#include "clang/AST/ExprConcepts.h"
14
#include "clang/AST/RecursiveASTVisitor.h"
15
#include "clang/AST/Type.h"
16
17
using namespace clang;
18
using namespace clang::index;
19
20
namespace {
21
22
class BodyIndexer : public RecursiveASTVisitor<BodyIndexer> {
23
  IndexingContext &IndexCtx;
24
  const NamedDecl *Parent;
25
  const DeclContext *ParentDC;
26
  SmallVector<Stmt*, 16> StmtStack;
27
28
  typedef RecursiveASTVisitor<BodyIndexer> base;
29
30
51
  Stmt *getParentStmt() const {
31
51
    return StmtStack.size() < 2 ? 
nullptr0
: StmtStack.end()[-2];
32
51
  }
33
public:
34
  BodyIndexer(IndexingContext &indexCtx,
35
              const NamedDecl *Parent, const DeclContext *DC)
36
274
    : IndexCtx(indexCtx), Parent(Parent), ParentDC(DC) { }
37
38
0
  bool shouldWalkTypesOfTypeLocs() const { return false; }
39
40
12.4k
  bool dataTraverseStmtPre(Stmt *S) {
41
12.4k
    StmtStack.push_back(S);
42
12.4k
    return true;
43
12.4k
  }
44
45
12.4k
  bool dataTraverseStmtPost(Stmt *S) {
46
12.4k
    assert(StmtStack.back() == S);
47
12.4k
    StmtStack.pop_back();
48
12.4k
    return true;
49
12.4k
  }
50
51
153
  bool TraverseTypeLoc(TypeLoc TL) {
52
153
    IndexCtx.indexTypeLoc(TL, Parent, ParentDC);
53
153
    return true;
54
153
  }
55
56
4.06k
  bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) {
57
4.06k
    IndexCtx.indexNestedNameSpecifierLoc(NNS, Parent, ParentDC);
58
4.06k
    return true;
59
4.06k
  }
60
61
  SymbolRoleSet getRolesForRef(const Expr *E,
62
3.99k
                               SmallVectorImpl<SymbolRelation> &Relations) {
63
3.99k
    SymbolRoleSet Roles{};
64
3.99k
    assert(!StmtStack.empty() && E == StmtStack.back());
65
3.99k
    if (StmtStack.size() == 1)
66
7
      return Roles;
67
3.98k
    auto It = StmtStack.end()-2;
68
7.86k
    while (isa<CastExpr>(*It) || 
isa<ParenExpr>(*It)3.97k
) {
69
3.89k
      if (auto ICE = dyn_cast<ImplicitCastExpr>(*It)) {
70
3.89k
        if (ICE->getCastKind() == CK_LValueToRValue)
71
2.11k
          Roles |= (unsigned)(unsigned)SymbolRole::Read;
72
3.89k
      }
73
3.89k
      if (It == StmtStack.begin())
74
19
        break;
75
3.88k
      --It;
76
3.88k
    }
77
3.98k
    const Stmt *Parent = *It;
78
79
3.98k
    if (auto BO = dyn_cast<BinaryOperator>(Parent)) {
80
2.03k
      if (BO->getOpcode() == BO_Assign && 
BO->getLHS()->IgnoreParenCasts() == E18
)
81
17
        Roles |= (unsigned)SymbolRole::Write;
82
83
2.03k
    } else 
if (auto 1.95k
UO1.95k
= dyn_cast<UnaryOperator>(Parent)) {
84
11
      if (UO->isIncrementDecrementOp()) {
85
6
        Roles |= (unsigned)SymbolRole::Read;
86
6
        Roles |= (unsigned)SymbolRole::Write;
87
6
      } else 
if (5
UO->getOpcode() == UO_AddrOf5
) {
88
3
        Roles |= (unsigned)SymbolRole::AddressOf;
89
3
      }
90
91
1.94k
    } else if (auto CA = dyn_cast<CompoundAssignOperator>(Parent)) {
92
0
      if (CA->getLHS()->IgnoreParenCasts() == E) {
93
0
        Roles |= (unsigned)SymbolRole::Read;
94
0
        Roles |= (unsigned)SymbolRole::Write;
95
0
      }
96
97
1.94k
    } else if (auto CE = dyn_cast<CallExpr>(Parent)) {
98
1.78k
      if (CE->getCallee()->IgnoreParenCasts() == E) {
99
1.77k
        addCallRole(Roles, Relations);
100
1.77k
        if (auto *ME = dyn_cast<MemberExpr>(E)) {
101
8
          if (auto *CXXMD = dyn_cast_or_null<CXXMethodDecl>(ME->getMemberDecl()))
102
8
            if (CXXMD->isVirtual() && 
!ME->hasQualifier()0
) {
103
0
              Roles |= (unsigned)SymbolRole::Dynamic;
104
0
              auto BaseTy = ME->getBase()->IgnoreImpCasts()->getType();
105
0
              if (!BaseTy.isNull())
106
0
                if (auto *CXXRD = BaseTy->getPointeeCXXRecordDecl())
107
0
                  Relations.emplace_back((unsigned)SymbolRole::RelationReceivedBy,
108
0
                                         CXXRD);
109
0
            }
110
8
        }
111
1.77k
      } else 
if (auto 7
CXXOp7
= dyn_cast<CXXOperatorCallExpr>(CE)) {
112
6
        if (CXXOp->getNumArgs() > 0 && CXXOp->getArg(0)->IgnoreParenCasts() == E) {
113
6
          OverloadedOperatorKind Op = CXXOp->getOperator();
114
6
          if (Op == OO_Equal) {
115
1
            Roles |= (unsigned)SymbolRole::Write;
116
5
          } else if ((Op >= OO_PlusEqual && 
Op <= OO_PipeEqual4
) ||
117
5
                     Op == OO_LessLessEqual || Op == OO_GreaterGreaterEqual ||
118
5
                     Op == OO_PlusPlus || 
Op == OO_MinusMinus4
) {
119
1
            Roles |= (unsigned)SymbolRole::Read;
120
1
            Roles |= (unsigned)SymbolRole::Write;
121
4
          } else if (Op == OO_Amp) {
122
0
            Roles |= (unsigned)SymbolRole::AddressOf;
123
0
          }
124
6
        }
125
6
      }
126
1.78k
    }
127
128
3.98k
    return Roles;
129
3.99k
  }
130
131
  void addCallRole(SymbolRoleSet &Roles,
132
1.86k
                   SmallVectorImpl<SymbolRelation> &Relations) {
133
1.86k
    Roles |= (unsigned)SymbolRole::Call;
134
1.86k
    if (auto *FD = dyn_cast<FunctionDecl>(ParentDC))
135
1.84k
      Relations.emplace_back((unsigned)SymbolRole::RelationCalledBy, FD);
136
26
    else if (auto *MD = dyn_cast<ObjCMethodDecl>(ParentDC))
137
16
      Relations.emplace_back((unsigned)SymbolRole::RelationCalledBy, MD);
138
1.86k
  }
139
140
3.94k
  bool VisitDeclRefExpr(DeclRefExpr *E) {
141
3.94k
    SmallVector<SymbolRelation, 4> Relations;
142
3.94k
    SymbolRoleSet Roles = getRolesForRef(E, Relations);
143
3.94k
    return IndexCtx.handleReference(E->getDecl(), E->getLocation(),
144
3.94k
                                    Parent, ParentDC, Roles, Relations, E);
145
3.94k
  }
146
147
2
  bool VisitGotoStmt(GotoStmt *S) {
148
2
    return IndexCtx.handleReference(S->getLabel(), S->getLabelLoc(), Parent,
149
2
                                    ParentDC);
150
2
  }
151
152
2
  bool VisitLabelStmt(LabelStmt *S) {
153
2
    if (IndexCtx.shouldIndexFunctionLocalSymbols())
154
1
      return IndexCtx.handleDecl(S->getDecl());
155
1
    return true;
156
2
  }
157
158
15
  bool VisitMemberExpr(MemberExpr *E) {
159
15
    SourceLocation Loc = E->getMemberLoc();
160
15
    if (Loc.isInvalid())
161
0
      Loc = E->getBeginLoc();
162
15
    SmallVector<SymbolRelation, 4> Relations;
163
15
    SymbolRoleSet Roles = getRolesForRef(E, Relations);
164
15
    return IndexCtx.handleReference(E->getMemberDecl(), Loc,
165
15
                                    Parent, ParentDC, Roles, Relations, E);
166
15
  }
167
168
  bool indexDependentReference(
169
      const Expr *E, const Type *T, const DeclarationNameInfo &NameInfo,
170
27
      llvm::function_ref<bool(const NamedDecl *ND)> Filter) {
171
27
    if (!T)
172
0
      return true;
173
27
    const TemplateSpecializationType *TST =
174
27
        T->getAs<TemplateSpecializationType>();
175
27
    if (!TST)
176
0
      return true;
177
27
    TemplateName TN = TST->getTemplateName();
178
27
    const ClassTemplateDecl *TD =
179
27
        dyn_cast_or_null<ClassTemplateDecl>(TN.getAsTemplateDecl());
180
27
    if (!TD)
181
0
      return true;
182
27
    CXXRecordDecl *RD = TD->getTemplatedDecl();
183
27
    if (!RD->hasDefinition())
184
1
      return true;
185
26
    RD = RD->getDefinition();
186
26
    std::vector<const NamedDecl *> Symbols =
187
26
        RD->lookupDependentName(NameInfo.getName(), Filter);
188
    // FIXME: Improve overload handling.
189
26
    if (Symbols.size() != 1)
190
13
      return true;
191
13
    SourceLocation Loc = NameInfo.getLoc();
192
13
    if (Loc.isInvalid())
193
0
      Loc = E->getBeginLoc();
194
13
    SmallVector<SymbolRelation, 4> Relations;
195
13
    SymbolRoleSet Roles = getRolesForRef(E, Relations);
196
13
    return IndexCtx.handleReference(Symbols[0], Loc, Parent, ParentDC, Roles,
197
13
                                    Relations, E);
198
26
  }
199
200
17
  bool VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E) {
201
17
    const DeclarationNameInfo &Info = E->getMemberNameInfo();
202
17
    return indexDependentReference(
203
17
        E, E->getBaseType().getTypePtrOrNull(), Info,
204
17
        [](const NamedDecl *D) 
{ return D->isCXXInstanceMember(); }16
);
205
17
  }
206
207
10
  bool VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E) {
208
10
    const DeclarationNameInfo &Info = E->getNameInfo();
209
10
    const NestedNameSpecifier *NNS = E->getQualifier();
210
10
    return indexDependentReference(
211
10
        E, NNS->getAsType(), Info,
212
10
        [](const NamedDecl *D) 
{ return !D->isCXXInstanceMember(); }9
);
213
10
  }
214
215
2
  bool VisitDesignatedInitExpr(DesignatedInitExpr *E) {
216
2
    for (DesignatedInitExpr::Designator &D : llvm::reverse(E->designators())) {
217
2
      if (D.isFieldDesignator()) {
218
2
        if (const FieldDecl *FD = D.getFieldDecl()) {
219
0
          return IndexCtx.handleReference(FD, D.getFieldLoc(), Parent,
220
0
                                          ParentDC, SymbolRoleSet(), {}, E);
221
0
        }
222
2
      }
223
2
    }
224
2
    return true;
225
2
  }
226
227
9
  bool VisitObjCIvarRefExpr(ObjCIvarRefExpr *E) {
228
9
    SmallVector<SymbolRelation, 4> Relations;
229
9
    SymbolRoleSet Roles = getRolesForRef(E, Relations);
230
9
    return IndexCtx.handleReference(E->getDecl(), E->getLocation(),
231
9
                                    Parent, ParentDC, Roles, Relations, E);
232
9
  }
233
234
51
  bool VisitObjCMessageExpr(ObjCMessageExpr *E) {
235
51
    auto isDynamic = [](const ObjCMessageExpr *MsgE)->bool {
236
51
      if (MsgE->getReceiverKind() != ObjCMessageExpr::Instance)
237
15
        return false;
238
36
      if (auto *RecE = dyn_cast<ObjCMessageExpr>(
239
36
              MsgE->getInstanceReceiver()->IgnoreParenCasts())) {
240
0
        if (RecE->getMethodFamily() == OMF_alloc)
241
0
          return false;
242
0
      }
243
36
      return true;
244
36
    };
245
246
51
    if (ObjCMethodDecl *MD = E->getMethodDecl()) {
247
51
      SymbolRoleSet Roles{};
248
51
      SmallVector<SymbolRelation, 2> Relations;
249
51
      addCallRole(Roles, Relations);
250
51
      Stmt *Containing = getParentStmt();
251
252
51
      auto IsImplicitProperty = [](const PseudoObjectExpr *POE) -> bool {
253
26
        const auto *E = POE->getSyntacticForm();
254
26
        if (const auto *BinOp = dyn_cast<BinaryOperator>(E))
255
12
          E = BinOp->getLHS();
256
26
        const auto *PRE = dyn_cast<ObjCPropertyRefExpr>(E);
257
26
        if (!PRE)
258
4
          return false;
259
22
        if (PRE->isExplicitProperty())
260
6
          return false;
261
16
        if (const ObjCMethodDecl *Getter = PRE->getImplicitPropertyGetter()) {
262
          // Class properties that are explicitly defined using @property
263
          // declarations are represented implicitly as there is no ivar for
264
          // class properties.
265
16
          if (Getter->isClassMethod() &&
266
16
              
Getter->getCanonicalDecl()->findPropertyDecl()12
)
267
4
            return false;
268
16
        }
269
12
        return true;
270
16
      };
271
51
      bool IsPropCall = Containing && isa<PseudoObjectExpr>(Containing);
272
      // Implicit property message sends are not 'implicit'.
273
51
      if ((E->isImplicit() || 
IsPropCall25
) &&
274
51
          
!(26
IsPropCall26
&&
275
26
            IsImplicitProperty(cast<PseudoObjectExpr>(Containing))))
276
14
        Roles |= (unsigned)SymbolRole::Implicit;
277
278
51
      if (isDynamic(E)) {
279
36
        Roles |= (unsigned)SymbolRole::Dynamic;
280
281
36
        auto addReceivers = [&](const ObjCObjectType *Ty) {
282
36
          if (!Ty)
283
0
            return;
284
36
          if (const auto *clsD = Ty->getInterface()) {
285
33
            Relations.emplace_back((unsigned)SymbolRole::RelationReceivedBy,
286
33
                                   clsD);
287
33
          }
288
36
          for (const auto *protD : Ty->quals()) {
289
9
            Relations.emplace_back((unsigned)SymbolRole::RelationReceivedBy,
290
9
                                   protD);
291
9
          }
292
36
        };
293
36
        QualType recT = E->getReceiverType();
294
36
        if (const auto *Ptr = recT->getAs<ObjCObjectPointerType>())
295
36
          addReceivers(Ptr->getObjectType());
296
0
        else
297
0
          addReceivers(recT->getAs<ObjCObjectType>());
298
36
      }
299
300
51
      return IndexCtx.handleReference(MD, E->getSelectorStartLoc(),
301
51
                                      Parent, ParentDC, Roles, Relations, E);
302
51
    }
303
0
    return true;
304
51
  }
305
306
22
  bool VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E) {
307
22
    if (E->isExplicitProperty()) {
308
6
      SmallVector<SymbolRelation, 2> Relations;
309
6
      SymbolRoleSet Roles = getRolesForRef(E, Relations);
310
6
      return IndexCtx.handleReference(E->getExplicitProperty(), E->getLocation(),
311
6
                                      Parent, ParentDC, Roles, Relations, E);
312
16
    } else if (const ObjCMethodDecl *Getter = E->getImplicitPropertyGetter()) {
313
      // Class properties that are explicitly defined using @property
314
      // declarations are represented implicitly as there is no ivar for class
315
      // properties.
316
16
      if (Getter->isClassMethod()) {
317
12
        if (const auto *PD = Getter->getCanonicalDecl()->findPropertyDecl()) {
318
4
          SmallVector<SymbolRelation, 2> Relations;
319
4
          SymbolRoleSet Roles = getRolesForRef(E, Relations);
320
4
          return IndexCtx.handleReference(PD, E->getLocation(), Parent,
321
4
                                          ParentDC, Roles, Relations, E);
322
4
        }
323
12
      }
324
16
    }
325
326
    // No need to do a handleReference for the objc method, because there will
327
    // be a message expr as part of PseudoObjectExpr.
328
12
    return true;
329
22
  }
330
331
2
  bool VisitMSPropertyRefExpr(MSPropertyRefExpr *E) {
332
2
    return IndexCtx.handleReference(E->getPropertyDecl(), E->getMemberLoc(),
333
2
                                    Parent, ParentDC, SymbolRoleSet(), {}, E);
334
2
  }
335
336
1
  bool VisitObjCProtocolExpr(ObjCProtocolExpr *E) {
337
1
    return IndexCtx.handleReference(E->getProtocol(), E->getProtocolIdLoc(),
338
1
                                    Parent, ParentDC, SymbolRoleSet(), {}, E);
339
1
  }
340
341
4
  bool passObjCLiteralMethodCall(const ObjCMethodDecl *MD, const Expr *E) {
342
4
    SymbolRoleSet Roles{};
343
4
    SmallVector<SymbolRelation, 2> Relations;
344
4
    addCallRole(Roles, Relations);
345
4
    Roles |= (unsigned)SymbolRole::Implicit;
346
4
    return IndexCtx.handleReference(MD, E->getBeginLoc(), Parent, ParentDC,
347
4
                                    Roles, Relations, E);
348
4
  }
349
350
2
  bool VisitObjCBoxedExpr(ObjCBoxedExpr *E) {
351
2
    if (ObjCMethodDecl *MD = E->getBoxingMethod()) {
352
2
      return passObjCLiteralMethodCall(MD, E);
353
2
    }
354
0
    return true;
355
2
  }
356
357
1
  bool VisitObjCDictionaryLiteral(ObjCDictionaryLiteral *E) {
358
1
    if (ObjCMethodDecl *MD = E->getDictWithObjectsMethod()) {
359
1
      return passObjCLiteralMethodCall(MD, E);
360
1
    }
361
0
    return true;
362
1
  }
363
364
1
  bool VisitObjCArrayLiteral(ObjCArrayLiteral *E) {
365
1
    if (ObjCMethodDecl *MD = E->getArrayWithObjectsMethod()) {
366
1
      return passObjCLiteralMethodCall(MD, E);
367
1
    }
368
0
    return true;
369
1
  }
370
371
32
  bool VisitCXXConstructExpr(CXXConstructExpr *E) {
372
32
    SymbolRoleSet Roles{};
373
32
    SmallVector<SymbolRelation, 2> Relations;
374
32
    addCallRole(Roles, Relations);
375
32
    return IndexCtx.handleReference(E->getConstructor(), E->getLocation(),
376
32
                                    Parent, ParentDC, Roles, Relations, E);
377
32
  }
378
379
  bool TraverseCXXOperatorCallExpr(CXXOperatorCallExpr *E,
380
1.74k
                                   DataRecursionQueue *Q = nullptr) {
381
1.74k
    if (E->getOperatorLoc().isInvalid())
382
0
      return true; // implicit.
383
1.74k
    return base::TraverseCXXOperatorCallExpr(E, Q);
384
1.74k
  }
385
386
66
  bool VisitDeclStmt(DeclStmt *S) {
387
66
    if (IndexCtx.shouldIndexFunctionLocalSymbols()) {
388
17
      IndexCtx.indexDeclGroupRef(S->getDeclGroup());
389
17
      return true;
390
17
    }
391
392
49
    DeclGroupRef DG = S->getDeclGroup();
393
98
    for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; 
++I49
) {
394
49
      const Decl *D = *I;
395
49
      if (!D)
396
0
        continue;
397
49
      if (!isFunctionLocalSymbol(D))
398
4
        IndexCtx.indexTopLevelDecl(D);
399
49
    }
400
401
49
    return true;
402
66
  }
403
404
  bool TraverseLambdaCapture(LambdaExpr *LE, const LambdaCapture *C,
405
8
                             Expr *Init) {
406
8
    if (C->capturesThis() || C->capturesVLAType())
407
0
      return true;
408
409
8
    if (!base::TraverseStmt(Init))
410
0
      return false;
411
412
8
    if (C->capturesVariable() && IndexCtx.shouldIndexFunctionLocalSymbols())
413
8
      return IndexCtx.handleReference(C->getCapturedVar(), C->getLocation(),
414
8
                                      Parent, ParentDC, SymbolRoleSet());
415
416
0
    return true;
417
8
  }
418
419
  // RecursiveASTVisitor visits both syntactic and semantic forms, duplicating
420
  // the things that we visit. Make sure to only visit the semantic form.
421
  // Also visit things that are in the syntactic form but not the semantic one,
422
  // for example the indices in DesignatedInitExprs.
423
15
  bool TraverseInitListExpr(InitListExpr *S, DataRecursionQueue *Q = nullptr) {
424
15
    auto visitForm = [&](InitListExpr *Form) {
425
15
      for (Stmt *SubStmt : Form->children()) {
426
15
        if (!TraverseStmt(SubStmt, Q))
427
0
          return false;
428
15
      }
429
15
      return true;
430
15
    };
431
432
15
    auto visitSyntacticDesignatedInitExpr = [&](DesignatedInitExpr *E) -> bool {
433
10
      for (DesignatedInitExpr::Designator &D : llvm::reverse(E->designators())) {
434
10
        if (D.isFieldDesignator()) {
435
4
          if (const FieldDecl *FD = D.getFieldDecl()) {
436
3
            return IndexCtx.handleReference(FD, D.getFieldLoc(), Parent,
437
3
                                            ParentDC, SymbolRoleSet(),
438
3
                                            /*Relations=*/{}, E);
439
3
          }
440
4
        }
441
10
      }
442
6
      return true;
443
9
    };
444
445
15
    InitListExpr *SemaForm = S->isSemanticForm() ? 
S14
:
S->getSemanticForm()1
;
446
15
    InitListExpr *SyntaxForm = S->isSemanticForm() ? 
S->getSyntacticForm()14
:
S1
;
447
448
15
    if (SemaForm) {
449
      // Visit things present in syntactic form but not the semantic form.
450
15
      if (SyntaxForm) {
451
13
        for (Expr *init : SyntaxForm->inits()) {
452
13
          if (auto *DIE = dyn_cast<DesignatedInitExpr>(init))
453
9
            visitSyntacticDesignatedInitExpr(DIE);
454
13
        }
455
12
      }
456
15
      return visitForm(SemaForm);
457
15
    }
458
459
    // No semantic, try the syntactic.
460
0
    if (SyntaxForm) {
461
0
      return visitForm(SyntaxForm);
462
0
    }
463
464
0
    return true;
465
0
  }
466
467
6
  bool VisitOffsetOfExpr(OffsetOfExpr *S) {
468
20
    for (unsigned I = 0, E = S->getNumComponents(); I != E; 
++I14
) {
469
14
      const OffsetOfNode &Component = S->getComponent(I);
470
14
      if (Component.getKind() == OffsetOfNode::Field)
471
8
        IndexCtx.handleReference(Component.getField(), Component.getEndLoc(),
472
8
                                 Parent, ParentDC, SymbolRoleSet(), {});
473
      // FIXME: Try to resolve dependent field references.
474
14
    }
475
6
    return true;
476
6
  }
477
478
6
  bool VisitParmVarDecl(ParmVarDecl* D) {
479
    // Index the parameters of lambda expression and requires expression.
480
6
    if (IndexCtx.shouldIndexFunctionLocalSymbols()) {
481
6
      const auto *DC = D->getDeclContext();
482
6
      if (DC && (isLambdaCallOperator(DC) || 
isa<RequiresExprBodyDecl>(DC)0
))
483
6
        IndexCtx.handleDecl(D);
484
6
    }
485
6
    return true;
486
6
  }
487
488
2
  bool VisitOverloadExpr(OverloadExpr *E) {
489
2
    SmallVector<SymbolRelation, 4> Relations;
490
2
    SymbolRoleSet Roles = getRolesForRef(E, Relations);
491
2
    for (auto *D : E->decls())
492
2
      IndexCtx.handleReference(D, E->getNameLoc(), Parent, ParentDC, Roles,
493
2
                               Relations, E);
494
2
    return true;
495
2
  }
496
497
0
  bool VisitConceptSpecializationExpr(ConceptSpecializationExpr *R) {
498
0
    IndexCtx.handleReference(R->getNamedConcept(), R->getConceptNameLoc(),
499
0
                             Parent, ParentDC);
500
0
    return true;
501
0
  }
502
503
0
  bool TraverseTypeConstraint(const TypeConstraint *C) {
504
0
    IndexCtx.handleReference(C->getNamedConcept(), C->getConceptNameLoc(),
505
0
                             Parent, ParentDC);
506
0
    return RecursiveASTVisitor::TraverseTypeConstraint(C);
507
0
  }
508
};
509
510
} // anonymous namespace
511
512
void IndexingContext::indexBody(const Stmt *S, const NamedDecl *Parent,
513
356
                                const DeclContext *DC) {
514
356
  if (!S)
515
82
    return;
516
517
274
  if (!DC)
518
78
    DC = Parent->getLexicalDeclContext();
519
274
  BodyIndexer(*this, Parent, DC).TraverseStmt(const_cast<Stmt*>(S));
520
274
}