Coverage Report

Created: 2022-01-15 10:30

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