Coverage Report

Created: 2023-09-12 09:32

/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/lib/Index/IndexTypeSourceInfo.cpp
Line
Count
Source (jump to first uncovered line)
1
//===- IndexTypeSourceInfo.cpp - Indexing types ---------------------------===//
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/PrettyPrinter.h"
12
#include "clang/AST/RecursiveASTVisitor.h"
13
#include "clang/AST/TypeLoc.h"
14
#include "llvm/ADT/ScopeExit.h"
15
16
using namespace clang;
17
using namespace index;
18
19
namespace {
20
21
class TypeIndexer : public RecursiveASTVisitor<TypeIndexer> {
22
  IndexingContext &IndexCtx;
23
  const NamedDecl *Parent;
24
  const DeclContext *ParentDC;
25
  bool IsBase;
26
  SmallVector<SymbolRelation, 3> Relations;
27
28
  typedef RecursiveASTVisitor<TypeIndexer> base;
29
30
public:
31
  TypeIndexer(IndexingContext &indexCtx, const NamedDecl *parent,
32
              const DeclContext *DC, bool isBase, bool isIBType)
33
1.10k
    : IndexCtx(indexCtx), Parent(parent), ParentDC(DC), IsBase(isBase) {
34
1.10k
    if (IsBase) {
35
34
      assert(Parent);
36
34
      Relations.emplace_back((unsigned)SymbolRole::RelationBaseOf, Parent);
37
34
    }
38
1.10k
    if (isIBType) {
39
6
      assert(Parent);
40
6
      Relations.emplace_back((unsigned)SymbolRole::RelationIBTypeOf, Parent);
41
6
    }
42
1.10k
  }
43
44
2.01k
  bool shouldWalkTypesOfTypeLocs() const { return false; }
45
46
#define TRY_TO(CALL_EXPR)                                                      \
47
201
  do {                                                                         \
48
201
    if (!CALL_EXPR)                                                            \
49
201
      
return false0
; \
50
201
  } while (0)
51
52
144
  bool VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TTPL) {
53
144
    SourceLocation Loc = TTPL.getNameLoc();
54
144
    TemplateTypeParmDecl *TTPD = TTPL.getDecl();
55
144
    return IndexCtx.handleReference(TTPD, Loc, Parent, ParentDC,
56
144
                                    SymbolRoleSet());
57
144
  }
58
59
114
  bool VisitTypedefTypeLoc(TypedefTypeLoc TL) {
60
114
    SourceLocation Loc = TL.getNameLoc();
61
114
    TypedefNameDecl *ND = TL.getTypedefNameDecl();
62
114
    if (ND->isTransparentTag()) {
63
5
      TagDecl *Underlying = ND->getUnderlyingType()->getAsTagDecl();
64
5
      return IndexCtx.handleReference(Underlying, Loc, Parent,
65
5
                                      ParentDC, SymbolRoleSet(), Relations);
66
5
    }
67
109
    if (IsBase) {
68
4
      TRY_TO(IndexCtx.handleReference(ND, Loc,
69
4
                                      Parent, ParentDC, SymbolRoleSet()));
70
4
      if (auto *CD = TL.getType()->getAsCXXRecordDecl()) {
71
2
        TRY_TO(IndexCtx.handleReference(CD, Loc, Parent, ParentDC,
72
2
                                        (unsigned)SymbolRole::Implicit,
73
2
                                        Relations));
74
2
      }
75
105
    } else {
76
105
      TRY_TO(IndexCtx.handleReference(ND, Loc,
77
105
                                      Parent, ParentDC, SymbolRoleSet(),
78
105
                                      Relations));
79
105
    }
80
109
    return true;
81
109
  }
82
83
13
  bool VisitAutoTypeLoc(AutoTypeLoc TL) {
84
13
    if (auto *C = TL.getNamedConcept())
85
0
      return IndexCtx.handleReference(C, TL.getConceptNameLoc(), Parent,
86
0
                                      ParentDC);
87
13
    return true;
88
13
  }
89
90
45
  bool traverseParamVarHelper(ParmVarDecl *D) {
91
45
    TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc()));
92
45
    if (D->getTypeSourceInfo())
93
45
      TRY_TO(TraverseTypeLoc(D->getTypeSourceInfo()->getTypeLoc()));
94
45
    return true;
95
45
  }
96
97
126
  bool TraverseParmVarDecl(ParmVarDecl *D) {
98
    // Avoid visiting default arguments from the definition that were already
99
    // visited in the declaration.
100
    // FIXME: A free function definition can have default arguments.
101
    // Avoiding double visitaiton of default arguments should be handled by the
102
    // visitor probably with a bit in the AST to indicate if the attached
103
    // default argument was 'inherited' or written in source.
104
126
    if (auto FD = dyn_cast<FunctionDecl>(D->getDeclContext())) {
105
110
      if (FD->isThisDeclarationADefinition()) {
106
45
        return traverseParamVarHelper(D);
107
45
      }
108
110
    }
109
110
81
    return base::TraverseParmVarDecl(D);
111
126
  }
112
113
149
  bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) {
114
149
    IndexCtx.indexNestedNameSpecifierLoc(NNS, Parent, ParentDC);
115
149
    return true;
116
149
  }
117
118
148
  bool VisitTagTypeLoc(TagTypeLoc TL) {
119
148
    TagDecl *D = TL.getDecl();
120
148
    if (!IndexCtx.shouldIndexFunctionLocalSymbols() &&
121
148
        
D->getParentFunctionOrMethod()99
)
122
0
      return true;
123
124
148
    if (TL.isDefinition()) {
125
4
      IndexCtx.indexTagDecl(D);
126
4
      return true;
127
4
    }
128
129
144
    return IndexCtx.handleReference(D, TL.getNameLoc(),
130
144
                                    Parent, ParentDC, SymbolRoleSet(),
131
144
                                    Relations);
132
148
  }
133
134
73
  bool VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) {
135
73
    return IndexCtx.handleReference(TL.getIFaceDecl(), TL.getNameLoc(),
136
73
                                    Parent, ParentDC, SymbolRoleSet(), Relations);
137
73
  }
138
139
84
  bool VisitObjCObjectTypeLoc(ObjCObjectTypeLoc TL) {
140
102
    for (unsigned i = 0, e = TL.getNumProtocols(); i != e; 
++i18
) {
141
18
      IndexCtx.handleReference(TL.getProtocol(i), TL.getProtocolLoc(i),
142
18
                               Parent, ParentDC, SymbolRoleSet(), Relations);
143
18
    }
144
84
    return true;
145
84
  }
146
147
  void HandleTemplateSpecializationTypeLoc(TemplateName TemplName,
148
                                           SourceLocation TemplNameLoc,
149
                                           CXXRecordDecl *ResolvedClass,
150
131
                                           bool IsTypeAlias) {
151
    // In presence of type aliases, the resolved class was never written in
152
    // the code so don't report it.
153
131
    if (!IsTypeAlias && ResolvedClass &&
154
131
        
(57
!ResolvedClass->isImplicit()57
||
155
57
         
IndexCtx.shouldIndexImplicitInstantiation()0
)) {
156
57
      IndexCtx.handleReference(ResolvedClass, TemplNameLoc, Parent, ParentDC,
157
57
                               SymbolRoleSet(), Relations);
158
74
    } else if (const TemplateDecl *D = TemplName.getAsTemplateDecl()) {
159
74
      IndexCtx.handleReference(D, TemplNameLoc, Parent, ParentDC,
160
74
                               SymbolRoleSet(), Relations);
161
74
    }
162
131
  }
163
164
129
  bool VisitTemplateSpecializationTypeLoc(TemplateSpecializationTypeLoc TL) {
165
129
    auto *T = TL.getTypePtr();
166
129
    if (!T)
167
0
      return true;
168
129
    HandleTemplateSpecializationTypeLoc(
169
129
        T->getTemplateName(), TL.getTemplateNameLoc(), T->getAsCXXRecordDecl(),
170
129
        T->isTypeAlias());
171
129
    return true;
172
129
  }
173
174
129
  bool TraverseTemplateSpecializationTypeLoc(TemplateSpecializationTypeLoc TL) {
175
129
    if (!WalkUpFromTemplateSpecializationTypeLoc(TL))
176
0
      return false;
177
129
    if (!TraverseTemplateName(TL.getTypePtr()->getTemplateName()))
178
0
      return false;
179
180
    // The relations we have to `Parent` do not apply to our template arguments,
181
    // so clear them while visiting the args.
182
129
    SmallVector<SymbolRelation, 3> SavedRelations = Relations;
183
129
    Relations.clear();
184
129
    auto ResetSavedRelations =
185
129
        llvm::make_scope_exit([&] { this->Relations = SavedRelations; });
186
312
    for (unsigned I = 0, E = TL.getNumArgs(); I != E; 
++I183
) {
187
183
      if (!TraverseTemplateArgumentLoc(TL.getArgLoc(I)))
188
0
        return false;
189
183
    }
190
191
129
    return true;
192
129
  }
193
194
2
  bool VisitDeducedTemplateSpecializationTypeLoc(DeducedTemplateSpecializationTypeLoc TL) {
195
2
    auto *T = TL.getTypePtr();
196
2
    if (!T)
197
0
      return true;
198
2
    HandleTemplateSpecializationTypeLoc(
199
2
        T->getTemplateName(), TL.getTemplateNameLoc(), T->getAsCXXRecordDecl(),
200
2
        /*IsTypeAlias=*/false);
201
2
    return true;
202
2
  }
203
204
3
  bool VisitInjectedClassNameTypeLoc(InjectedClassNameTypeLoc TL) {
205
3
    return IndexCtx.handleReference(TL.getDecl(), TL.getNameLoc(), Parent,
206
3
                                    ParentDC, SymbolRoleSet(), Relations);
207
3
  }
208
209
15
  bool VisitDependentNameTypeLoc(DependentNameTypeLoc TL) {
210
15
    const DependentNameType *DNT = TL.getTypePtr();
211
15
    const NestedNameSpecifier *NNS = DNT->getQualifier();
212
15
    const Type *T = NNS->getAsType();
213
15
    if (!T)
214
0
      return true;
215
15
    const TemplateSpecializationType *TST =
216
15
        T->getAs<TemplateSpecializationType>();
217
15
    if (!TST)
218
0
      return true;
219
15
    TemplateName TN = TST->getTemplateName();
220
15
    const ClassTemplateDecl *TD =
221
15
        dyn_cast_or_null<ClassTemplateDecl>(TN.getAsTemplateDecl());
222
15
    if (!TD)
223
0
      return true;
224
15
    CXXRecordDecl *RD = TD->getTemplatedDecl();
225
15
    if (!RD->hasDefinition())
226
2
      return true;
227
13
    RD = RD->getDefinition();
228
13
    DeclarationName Name(DNT->getIdentifier());
229
13
    std::vector<const NamedDecl *> Symbols = RD->lookupDependentName(
230
13
        Name, [](const NamedDecl *ND) 
{ return isa<TypeDecl>(ND); }11
);
231
13
    if (Symbols.size() != 1)
232
4
      return true;
233
9
    return IndexCtx.handleReference(Symbols[0], TL.getNameLoc(), Parent,
234
9
                                    ParentDC, SymbolRoleSet(), Relations);
235
13
  }
236
237
26
  bool TraverseStmt(Stmt *S) {
238
26
    IndexCtx.indexBody(S, Parent, ParentDC);
239
26
    return true;
240
26
  }
241
};
242
243
} // anonymous namespace
244
245
void IndexingContext::indexTypeSourceInfo(TypeSourceInfo *TInfo,
246
                                          const NamedDecl *Parent,
247
                                          const DeclContext *DC,
248
                                          bool isBase,
249
950
                                          bool isIBType) {
250
950
  if (!TInfo || 
TInfo->getTypeLoc().isNull()870
)
251
80
    return;
252
253
870
  indexTypeLoc(TInfo->getTypeLoc(), Parent, DC, isBase, isIBType);
254
870
}
255
256
void IndexingContext::indexTypeLoc(TypeLoc TL,
257
                                   const NamedDecl *Parent,
258
                                   const DeclContext *DC,
259
                                   bool isBase,
260
1.10k
                                   bool isIBType) {
261
1.10k
  if (TL.isNull())
262
0
    return;
263
264
1.10k
  if (!DC)
265
281
    DC = Parent->getLexicalDeclContext();
266
1.10k
  TypeIndexer(*this, Parent, DC, isBase, isIBType).TraverseTypeLoc(TL);
267
1.10k
}
268
269
void IndexingContext::indexNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS,
270
                                                  const NamedDecl *Parent,
271
4.99k
                                                  const DeclContext *DC) {
272
4.99k
  if (!NNS)
273
4.88k
    return;
274
275
107
  if (NestedNameSpecifierLoc Prefix = NNS.getPrefix())
276
19
    indexNestedNameSpecifierLoc(Prefix, Parent, DC);
277
278
107
  if (!DC)
279
32
    DC = Parent->getLexicalDeclContext();
280
107
  SourceLocation Loc = NNS.getLocalBeginLoc();
281
282
107
  switch (NNS.getNestedNameSpecifier()->getKind()) {
283
0
  case NestedNameSpecifier::Identifier:
284
5
  case NestedNameSpecifier::Global:
285
5
  case NestedNameSpecifier::Super:
286
5
    break;
287
288
23
  case NestedNameSpecifier::Namespace:
289
23
    handleReference(NNS.getNestedNameSpecifier()->getAsNamespace(),
290
23
                    Loc, Parent, DC, SymbolRoleSet());
291
23
    break;
292
2
  case NestedNameSpecifier::NamespaceAlias:
293
2
    handleReference(NNS.getNestedNameSpecifier()->getAsNamespaceAlias(),
294
2
                    Loc, Parent, DC, SymbolRoleSet());
295
2
    break;
296
297
77
  case NestedNameSpecifier::TypeSpec:
298
77
  case NestedNameSpecifier::TypeSpecWithTemplate:
299
77
    indexTypeLoc(NNS.getTypeLoc(), Parent, DC);
300
77
    break;
301
107
  }
302
107
}
303
304
void IndexingContext::indexTagDecl(const TagDecl *D,
305
228
                                   ArrayRef<SymbolRelation> Relations) {
306
228
  if (!shouldIndex(D))
307
3
    return;
308
225
  if (!shouldIndexFunctionLocalSymbols() && 
isFunctionLocalSymbol(D)159
)
309
0
    return;
310
311
225
  if (handleDecl(D, /*Roles=*/SymbolRoleSet(), Relations)) {
312
225
    if (D->isThisDeclarationADefinition()) {
313
218
      indexNestedNameSpecifierLoc(D->getQualifierLoc(), D);
314
218
      if (auto CXXRD = dyn_cast<CXXRecordDecl>(D)) {
315
189
        for (const auto &I : CXXRD->bases()) {
316
26
          indexTypeSourceInfo(I.getTypeSourceInfo(), CXXRD, CXXRD, /*isBase=*/true);
317
26
        }
318
189
      }
319
218
      indexDeclContext(D);
320
218
    }
321
225
  }
322
225
}