1 | //===- IndexingContext.cpp - Indexing context data ------------------------===// |
---|---|
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/ASTContext.h" |
11 | #include "clang/AST/Attr.h" |
12 | #include "clang/AST/DeclObjC.h" |
13 | #include "clang/AST/DeclTemplate.h" |
14 | #include "clang/Basic/SourceLocation.h" |
15 | #include "clang/Basic/SourceManager.h" |
16 | #include "clang/Index/IndexDataConsumer.h" |
17 | #include "clang/Sema/HeuristicResolver.h" |
18 | |
19 | using namespace clang; |
20 | using namespace index; |
21 | |
22 | static bool isGeneratedDecl(const Decl *D) { |
23 | if (auto *attr = D->getAttr<ExternalSourceSymbolAttr>()) { |
24 | return attr->getGeneratedDeclaration(); |
25 | } |
26 | return false; |
27 | } |
28 | |
29 | IndexingContext::IndexingContext(IndexingOptions IndexOpts, |
30 | IndexDataConsumer &DataConsumer) |
31 | : IndexOpts(IndexOpts), DataConsumer(DataConsumer) {} |
32 | |
33 | IndexingContext::~IndexingContext() = default; |
34 | |
35 | void IndexingContext::setASTContext(ASTContext &ctx) { |
36 | Ctx = &ctx; |
37 | Resolver = Ctx ? std::make_unique<HeuristicResolver>(args&: *Ctx) : nullptr; |
38 | } |
39 | |
40 | bool IndexingContext::shouldIndex(const Decl *D) { |
41 | return !isGeneratedDecl(D); |
42 | } |
43 | |
44 | const LangOptions &IndexingContext::getLangOpts() const { |
45 | return Ctx->getLangOpts(); |
46 | } |
47 | |
48 | bool IndexingContext::shouldIndexFunctionLocalSymbols() const { |
49 | return IndexOpts.IndexFunctionLocals; |
50 | } |
51 | |
52 | bool IndexingContext::shouldIndexImplicitInstantiation() const { |
53 | return IndexOpts.IndexImplicitInstantiation; |
54 | } |
55 | |
56 | bool IndexingContext::shouldIndexParametersInDeclarations() const { |
57 | return IndexOpts.IndexParametersInDeclarations; |
58 | } |
59 | |
60 | bool IndexingContext::shouldIndexTemplateParameters() const { |
61 | return IndexOpts.IndexTemplateParameters; |
62 | } |
63 | |
64 | bool IndexingContext::handleDecl(const Decl *D, |
65 | SymbolRoleSet Roles, |
66 | ArrayRef<SymbolRelation> Relations) { |
67 | return handleDecl(D, Loc: D->getLocation(), Roles, Relations); |
68 | } |
69 | |
70 | bool IndexingContext::handleDecl(const Decl *D, SourceLocation Loc, |
71 | SymbolRoleSet Roles, |
72 | ArrayRef<SymbolRelation> Relations, |
73 | const DeclContext *DC) { |
74 | if (!DC) |
75 | DC = D->getDeclContext(); |
76 | |
77 | const Decl *OrigD = D; |
78 | if (isa<ObjCPropertyImplDecl>(Val: D)) { |
79 | D = cast<ObjCPropertyImplDecl>(Val: D)->getPropertyDecl(); |
80 | } |
81 | return handleDeclOccurrence(D, Loc, /*IsRef=*/false, Parent: cast<Decl>(Val: DC), |
82 | Roles, Relations, |
83 | RefE: nullptr, RefD: OrigD, ContainerDC: DC); |
84 | } |
85 | |
86 | bool IndexingContext::handleReference(const NamedDecl *D, SourceLocation Loc, |
87 | const NamedDecl *Parent, |
88 | const DeclContext *DC, |
89 | SymbolRoleSet Roles, |
90 | ArrayRef<SymbolRelation> Relations, |
91 | const Expr *RefE) { |
92 | if (!shouldIndexFunctionLocalSymbols() && isFunctionLocalSymbol(D)) |
93 | return true; |
94 | |
95 | if (!shouldIndexTemplateParameters() && |
96 | (isa<NonTypeTemplateParmDecl>(Val: D) || isa<TemplateTypeParmDecl>(Val: D) || |
97 | isa<TemplateTemplateParmDecl>(Val: D))) { |
98 | return true; |
99 | } |
100 | return handleDeclOccurrence(D, Loc, /*IsRef=*/true, Parent, Roles, Relations, |
101 | RefE, nullptr, DC); |
102 | } |
103 | |
104 | static void reportModuleReferences(const Module *Mod, |
105 | ArrayRef<SourceLocation> IdLocs, |
106 | const ImportDecl *ImportD, |
107 | IndexDataConsumer &DataConsumer) { |
108 | if (!Mod) |
109 | return; |
110 | reportModuleReferences(Mod: Mod->Parent, IdLocs: IdLocs.drop_back(), ImportD, |
111 | DataConsumer); |
112 | DataConsumer.handleModuleOccurrence( |
113 | ImportD, Mod, Roles: (SymbolRoleSet)SymbolRole::Reference, Loc: IdLocs.back()); |
114 | } |
115 | |
116 | bool IndexingContext::importedModule(const ImportDecl *ImportD) { |
117 | if (ImportD->isInvalidDecl()) |
118 | return true; |
119 | |
120 | SourceLocation Loc; |
121 | auto IdLocs = ImportD->getIdentifierLocs(); |
122 | if (!IdLocs.empty()) |
123 | Loc = IdLocs.back(); |
124 | else |
125 | Loc = ImportD->getLocation(); |
126 | |
127 | SourceManager &SM = Ctx->getSourceManager(); |
128 | FileID FID = SM.getFileID(SpellingLoc: SM.getFileLoc(Loc)); |
129 | if (FID.isInvalid()) |
130 | return true; |
131 | |
132 | bool Invalid = false; |
133 | const SrcMgr::SLocEntry &SEntry = SM.getSLocEntry(FID, Invalid: &Invalid); |
134 | if (Invalid || !SEntry.isFile()) |
135 | return true; |
136 | |
137 | if (SEntry.getFile().getFileCharacteristic() != SrcMgr::C_User) { |
138 | switch (IndexOpts.SystemSymbolFilter) { |
139 | case IndexingOptions::SystemSymbolFilterKind::None: |
140 | return true; |
141 | case IndexingOptions::SystemSymbolFilterKind::DeclarationsOnly: |
142 | case IndexingOptions::SystemSymbolFilterKind::All: |
143 | break; |
144 | } |
145 | } |
146 | |
147 | const Module *Mod = ImportD->getImportedModule(); |
148 | if (!ImportD->isImplicit() && Mod->Parent && !IdLocs.empty()) { |
149 | reportModuleReferences(Mod: Mod->Parent, IdLocs: IdLocs.drop_back(), ImportD, |
150 | DataConsumer); |
151 | } |
152 | |
153 | SymbolRoleSet Roles = (unsigned)SymbolRole::Declaration; |
154 | if (ImportD->isImplicit()) |
155 | Roles |= (unsigned)SymbolRole::Implicit; |
156 | |
157 | return DataConsumer.handleModuleOccurrence(ImportD, Mod, Roles, Loc); |
158 | } |
159 | |
160 | bool IndexingContext::isTemplateImplicitInstantiation(const Decl *D) { |
161 | TemplateSpecializationKind TKind = TSK_Undeclared; |
162 | if (const ClassTemplateSpecializationDecl * |
163 | SD = dyn_cast<ClassTemplateSpecializationDecl>(Val: D)) { |
164 | TKind = SD->getSpecializationKind(); |
165 | } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(Val: D)) { |
166 | TKind = FD->getTemplateSpecializationKind(); |
167 | } else if (auto *VD = dyn_cast<VarDecl>(Val: D)) { |
168 | TKind = VD->getTemplateSpecializationKind(); |
169 | } else if (const auto *RD = dyn_cast<CXXRecordDecl>(Val: D)) { |
170 | if (RD->getInstantiatedFromMemberClass()) |
171 | TKind = RD->getTemplateSpecializationKind(); |
172 | } else if (const auto *ED = dyn_cast<EnumDecl>(Val: D)) { |
173 | if (ED->getInstantiatedFromMemberEnum()) |
174 | TKind = ED->getTemplateSpecializationKind(); |
175 | } else if (isa<FieldDecl>(Val: D) || isa<TypedefNameDecl>(Val: D) || |
176 | isa<EnumConstantDecl>(Val: D)) { |
177 | if (const auto *Parent = dyn_cast<Decl>(Val: D->getDeclContext())) |
178 | return isTemplateImplicitInstantiation(D: Parent); |
179 | } |
180 | switch (TKind) { |
181 | case TSK_Undeclared: |
182 | // Instantiation maybe not happen yet when we see a SpecializationDecl, |
183 | // e.g. when the type doesn't need to be complete, we still treat it as an |
184 | // instantiation as we'd like to keep the canonicalized result consistent. |
185 | return isa<ClassTemplateSpecializationDecl>(Val: D); |
186 | case TSK_ExplicitSpecialization: |
187 | return false; |
188 | case TSK_ImplicitInstantiation: |
189 | case TSK_ExplicitInstantiationDeclaration: |
190 | case TSK_ExplicitInstantiationDefinition: |
191 | return true; |
192 | } |
193 | llvm_unreachable("invalid TemplateSpecializationKind"); |
194 | } |
195 | |
196 | bool IndexingContext::shouldIgnoreIfImplicit(const Decl *D) { |
197 | if (isa<ObjCInterfaceDecl>(Val: D)) |
198 | return false; |
199 | if (isa<ObjCCategoryDecl>(Val: D)) |
200 | return false; |
201 | if (isa<ObjCIvarDecl>(Val: D)) |
202 | return false; |
203 | if (isa<ObjCMethodDecl>(Val: D)) |
204 | return false; |
205 | if (isa<ImportDecl>(Val: D)) |
206 | return false; |
207 | return true; |
208 | } |
209 | |
210 | static const CXXRecordDecl * |
211 | getDeclContextForTemplateInstationPattern(const Decl *D) { |
212 | if (const auto *CTSD = |
213 | dyn_cast<ClassTemplateSpecializationDecl>(Val: D->getDeclContext())) |
214 | return CTSD->getTemplateInstantiationPattern(); |
215 | else if (const auto *RD = dyn_cast<CXXRecordDecl>(Val: D->getDeclContext())) |
216 | return RD->getInstantiatedFromMemberClass(); |
217 | return nullptr; |
218 | } |
219 | |
220 | static const Decl *adjustTemplateImplicitInstantiation(const Decl *D) { |
221 | if (const ClassTemplateSpecializationDecl * |
222 | SD = dyn_cast<ClassTemplateSpecializationDecl>(Val: D)) { |
223 | const auto *Template = SD->getTemplateInstantiationPattern(); |
224 | if (Template) |
225 | return Template; |
226 | // Fallback to primary template if no instantiation is available yet (e.g. |
227 | // the type doesn't need to be complete). |
228 | return SD->getSpecializedTemplate()->getTemplatedDecl(); |
229 | } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(Val: D)) { |
230 | return FD->getTemplateInstantiationPattern(); |
231 | } else if (auto *VD = dyn_cast<VarDecl>(Val: D)) { |
232 | return VD->getTemplateInstantiationPattern(); |
233 | } else if (const auto *RD = dyn_cast<CXXRecordDecl>(Val: D)) { |
234 | return RD->getInstantiatedFromMemberClass(); |
235 | } else if (const auto *ED = dyn_cast<EnumDecl>(Val: D)) { |
236 | return ED->getInstantiatedFromMemberEnum(); |
237 | } else if (isa<FieldDecl>(Val: D) || isa<TypedefNameDecl>(Val: D)) { |
238 | const auto *ND = cast<NamedDecl>(Val: D); |
239 | if (const CXXRecordDecl *Pattern = |
240 | getDeclContextForTemplateInstationPattern(ND)) { |
241 | for (const NamedDecl *BaseND : Pattern->lookup(ND->getDeclName())) { |
242 | if (BaseND->isImplicit()) |
243 | continue; |
244 | if (BaseND->getKind() == ND->getKind()) |
245 | return BaseND; |
246 | } |
247 | } |
248 | } else if (const auto *ECD = dyn_cast<EnumConstantDecl>(Val: D)) { |
249 | if (const auto *ED = dyn_cast<EnumDecl>(ECD->getDeclContext())) { |
250 | if (const EnumDecl *Pattern = ED->getInstantiatedFromMemberEnum()) { |
251 | for (const NamedDecl *BaseECD : Pattern->lookup(ECD->getDeclName())) |
252 | return BaseECD; |
253 | } |
254 | } |
255 | } |
256 | return nullptr; |
257 | } |
258 | |
259 | static bool isDeclADefinition(const Decl *D, const DeclContext *ContainerDC, ASTContext &Ctx) { |
260 | if (auto VD = dyn_cast<VarDecl>(Val: D)) |
261 | return VD->isThisDeclarationADefinition(Ctx); |
262 | |
263 | if (auto FD = dyn_cast<FunctionDecl>(Val: D)) |
264 | return FD->isThisDeclarationADefinition(); |
265 | |
266 | if (auto TD = dyn_cast<TagDecl>(Val: D)) |
267 | return TD->isThisDeclarationADefinition(); |
268 | |
269 | if (auto MD = dyn_cast<ObjCMethodDecl>(Val: D)) |
270 | return MD->isThisDeclarationADefinition() || isa<ObjCImplDecl>(Val: ContainerDC); |
271 | |
272 | if (isa<TypedefNameDecl>(Val: D) || isa<EnumConstantDecl>(Val: D) || |
273 | isa<FieldDecl>(Val: D) || isa<MSPropertyDecl>(Val: D) || isa<ObjCImplDecl>(Val: D) || |
274 | isa<ObjCPropertyImplDecl>(Val: D) || isa<ConceptDecl>(Val: D)) |
275 | return true; |
276 | |
277 | return false; |
278 | } |
279 | |
280 | /// Whether the given NamedDecl should be skipped because it has no name. |
281 | static bool shouldSkipNamelessDecl(const NamedDecl *ND) { |
282 | return (ND->getDeclName().isEmpty() && !isa<TagDecl>(Val: ND) && |
283 | !isa<ObjCCategoryDecl>(Val: ND)) || isa<CXXDeductionGuideDecl>(Val: ND); |
284 | } |
285 | |
286 | static const Decl *adjustParent(const Decl *Parent) { |
287 | if (!Parent) |
288 | return nullptr; |
289 | for (;; Parent = cast<Decl>(Val: Parent->getDeclContext())) { |
290 | if (isa<TranslationUnitDecl>(Val: Parent)) |
291 | return nullptr; |
292 | if (isa<LinkageSpecDecl>(Val: Parent) || isa<BlockDecl>(Val: Parent)) |
293 | continue; |
294 | if (auto NS = dyn_cast<NamespaceDecl>(Val: Parent)) { |
295 | if (NS->isAnonymousNamespace()) |
296 | continue; |
297 | } else if (auto RD = dyn_cast<RecordDecl>(Val: Parent)) { |
298 | if (RD->isAnonymousStructOrUnion()) |
299 | continue; |
300 | } else if (auto ND = dyn_cast<NamedDecl>(Val: Parent)) { |
301 | if (shouldSkipNamelessDecl(ND)) |
302 | continue; |
303 | } |
304 | return Parent; |
305 | } |
306 | } |
307 | |
308 | static const Decl *getCanonicalDecl(const Decl *D) { |
309 | D = D->getCanonicalDecl(); |
310 | if (auto TD = dyn_cast<TemplateDecl>(Val: D)) { |
311 | if (auto TTD = TD->getTemplatedDecl()) { |
312 | D = TTD; |
313 | assert(D->isCanonicalDecl()); |
314 | } |
315 | } |
316 | |
317 | return D; |
318 | } |
319 | |
320 | static bool shouldReportOccurrenceForSystemDeclOnlyMode( |
321 | bool IsRef, SymbolRoleSet Roles, ArrayRef<SymbolRelation> Relations) { |
322 | if (!IsRef) |
323 | return true; |
324 | |
325 | auto acceptForRelation = [](SymbolRoleSet roles) -> bool { |
326 | bool accept = false; |
327 | applyForEachSymbolRoleInterruptible(Roles: roles, Fn: [&accept](SymbolRole r) -> bool { |
328 | switch (r) { |
329 | case SymbolRole::RelationChildOf: |
330 | case SymbolRole::RelationBaseOf: |
331 | case SymbolRole::RelationOverrideOf: |
332 | case SymbolRole::RelationExtendedBy: |
333 | case SymbolRole::RelationAccessorOf: |
334 | case SymbolRole::RelationIBTypeOf: |
335 | accept = true; |
336 | return false; |
337 | case SymbolRole::Declaration: |
338 | case SymbolRole::Definition: |
339 | case SymbolRole::Reference: |
340 | case SymbolRole::Read: |
341 | case SymbolRole::Write: |
342 | case SymbolRole::Call: |
343 | case SymbolRole::Dynamic: |
344 | case SymbolRole::AddressOf: |
345 | case SymbolRole::Implicit: |
346 | case SymbolRole::Undefinition: |
347 | case SymbolRole::RelationReceivedBy: |
348 | case SymbolRole::RelationCalledBy: |
349 | case SymbolRole::RelationContainedBy: |
350 | case SymbolRole::RelationSpecializationOf: |
351 | case SymbolRole::NameReference: |
352 | return true; |
353 | } |
354 | llvm_unreachable("Unsupported SymbolRole value!"); |
355 | }); |
356 | return accept; |
357 | }; |
358 | |
359 | for (auto &Rel : Relations) { |
360 | if (acceptForRelation(Rel.Roles)) |
361 | return true; |
362 | } |
363 | |
364 | return false; |
365 | } |
366 | |
367 | bool IndexingContext::handleDeclOccurrence(const Decl *D, SourceLocation Loc, |
368 | bool IsRef, const Decl *Parent, |
369 | SymbolRoleSet Roles, |
370 | ArrayRef<SymbolRelation> Relations, |
371 | const Expr *OrigE, |
372 | const Decl *OrigD, |
373 | const DeclContext *ContainerDC) { |
374 | if (D->isImplicit() && !isa<ObjCMethodDecl>(Val: D)) |
375 | return true; |
376 | if (!isa<NamedDecl>(Val: D) || shouldSkipNamelessDecl(ND: cast<NamedDecl>(Val: D))) |
377 | return true; |
378 | |
379 | SourceManager &SM = Ctx->getSourceManager(); |
380 | FileID FID = SM.getFileID(SpellingLoc: SM.getFileLoc(Loc)); |
381 | if (FID.isInvalid()) |
382 | return true; |
383 | |
384 | bool Invalid = false; |
385 | const SrcMgr::SLocEntry &SEntry = SM.getSLocEntry(FID, Invalid: &Invalid); |
386 | if (Invalid || !SEntry.isFile()) |
387 | return true; |
388 | |
389 | if (SEntry.getFile().getFileCharacteristic() != SrcMgr::C_User) { |
390 | switch (IndexOpts.SystemSymbolFilter) { |
391 | case IndexingOptions::SystemSymbolFilterKind::None: |
392 | return true; |
393 | case IndexingOptions::SystemSymbolFilterKind::DeclarationsOnly: |
394 | if (!shouldReportOccurrenceForSystemDeclOnlyMode(IsRef, Roles, Relations)) |
395 | return true; |
396 | break; |
397 | case IndexingOptions::SystemSymbolFilterKind::All: |
398 | break; |
399 | } |
400 | } |
401 | |
402 | if (!OrigD) |
403 | OrigD = D; |
404 | |
405 | if (isTemplateImplicitInstantiation(D)) { |
406 | if (!IsRef) |
407 | return true; |
408 | D = adjustTemplateImplicitInstantiation(D); |
409 | if (!D) |
410 | return true; |
411 | assert(!isTemplateImplicitInstantiation(D)); |
412 | } |
413 | |
414 | if (IsRef) |
415 | Roles |= (unsigned)SymbolRole::Reference; |
416 | else if (isDeclADefinition(D: OrigD, ContainerDC, Ctx&: *Ctx)) |
417 | Roles |= (unsigned)SymbolRole::Definition; |
418 | else |
419 | Roles |= (unsigned)SymbolRole::Declaration; |
420 | |
421 | D = getCanonicalDecl(D); |
422 | Parent = adjustParent(Parent); |
423 | if (Parent) |
424 | Parent = getCanonicalDecl(D: Parent); |
425 | |
426 | SmallVector<SymbolRelation, 6> FinalRelations; |
427 | FinalRelations.reserve(N: Relations.size()+1); |
428 | |
429 | auto addRelation = [&](SymbolRelation Rel) { |
430 | auto It = llvm::find_if(Range&: FinalRelations, P: [&](SymbolRelation Elem) -> bool { |
431 | return Elem.RelatedSymbol == Rel.RelatedSymbol; |
432 | }); |
433 | if (It != FinalRelations.end()) { |
434 | It->Roles |= Rel.Roles; |
435 | } else { |
436 | FinalRelations.push_back(Elt: Rel); |
437 | } |
438 | Roles |= Rel.Roles; |
439 | }; |
440 | |
441 | if (Parent) { |
442 | if (IsRef || (!isa<ParmVarDecl>(Val: D) && isFunctionLocalSymbol(D))) { |
443 | addRelation(SymbolRelation{ |
444 | (unsigned)SymbolRole::RelationContainedBy, |
445 | Parent |
446 | }); |
447 | } else { |
448 | addRelation(SymbolRelation{ |
449 | (unsigned)SymbolRole::RelationChildOf, |
450 | Parent |
451 | }); |
452 | } |
453 | } |
454 | |
455 | for (auto &Rel : Relations) { |
456 | addRelation(SymbolRelation(Rel.Roles, |
457 | Rel.RelatedSymbol->getCanonicalDecl())); |
458 | } |
459 | |
460 | IndexDataConsumer::ASTNodeInfo Node{.OrigE: OrigE, .OrigD: OrigD, .Parent: Parent, .ContainerDC: ContainerDC}; |
461 | return DataConsumer.handleDeclOccurrence(D, Roles, Relations: FinalRelations, Loc, ASTNode: Node); |
462 | } |
463 | |
464 | void IndexingContext::handleMacroDefined(const IdentifierInfo &Name, |
465 | SourceLocation Loc, |
466 | const MacroInfo &MI) { |
467 | if (!shouldIndexMacroOccurrence(/*IsRef=*/false, Loc)) |
468 | return; |
469 | SymbolRoleSet Roles = (unsigned)SymbolRole::Definition; |
470 | DataConsumer.handleMacroOccurrence(Name: &Name, MI: &MI, Roles, Loc); |
471 | } |
472 | |
473 | void IndexingContext::handleMacroUndefined(const IdentifierInfo &Name, |
474 | SourceLocation Loc, |
475 | const MacroInfo &MI) { |
476 | if (!shouldIndexMacroOccurrence(/*IsRef=*/false, Loc)) |
477 | return; |
478 | SymbolRoleSet Roles = (unsigned)SymbolRole::Undefinition; |
479 | DataConsumer.handleMacroOccurrence(Name: &Name, MI: &MI, Roles, Loc); |
480 | } |
481 | |
482 | void IndexingContext::handleMacroReference(const IdentifierInfo &Name, |
483 | SourceLocation Loc, |
484 | const MacroInfo &MI) { |
485 | if (!shouldIndexMacroOccurrence(/*IsRef=*/true, Loc)) |
486 | return; |
487 | SymbolRoleSet Roles = (unsigned)SymbolRole::Reference; |
488 | DataConsumer.handleMacroOccurrence(Name: &Name, MI: &MI, Roles, Loc); |
489 | } |
490 | |
491 | bool IndexingContext::shouldIndexMacroOccurrence(bool IsRef, |
492 | SourceLocation Loc) { |
493 | if (!IndexOpts.IndexMacros) |
494 | return false; |
495 | |
496 | switch (IndexOpts.SystemSymbolFilter) { |
497 | case IndexingOptions::SystemSymbolFilterKind::None: |
498 | break; |
499 | case IndexingOptions::SystemSymbolFilterKind::DeclarationsOnly: |
500 | if (!IsRef) |
501 | return true; |
502 | break; |
503 | case IndexingOptions::SystemSymbolFilterKind::All: |
504 | return true; |
505 | } |
506 | |
507 | SourceManager &SM = Ctx->getSourceManager(); |
508 | FileID FID = SM.getFileID(SpellingLoc: SM.getFileLoc(Loc)); |
509 | if (FID.isInvalid()) |
510 | return false; |
511 | |
512 | bool Invalid = false; |
513 | const SrcMgr::SLocEntry &SEntry = SM.getSLocEntry(FID, Invalid: &Invalid); |
514 | if (Invalid || !SEntry.isFile()) |
515 | return false; |
516 | |
517 | return SEntry.getFile().getFileCharacteristic() == SrcMgr::C_User; |
518 | } |
519 |
Definitions
- isGeneratedDecl
- IndexingContext
- ~IndexingContext
- setASTContext
- shouldIndex
- getLangOpts
- shouldIndexFunctionLocalSymbols
- shouldIndexImplicitInstantiation
- shouldIndexParametersInDeclarations
- shouldIndexTemplateParameters
- handleDecl
- handleDecl
- handleReference
- reportModuleReferences
- importedModule
- isTemplateImplicitInstantiation
- shouldIgnoreIfImplicit
- getDeclContextForTemplateInstationPattern
- adjustTemplateImplicitInstantiation
- isDeclADefinition
- shouldSkipNamelessDecl
- adjustParent
- getCanonicalDecl
- shouldReportOccurrenceForSystemDeclOnlyMode
- handleDeclOccurrence
- handleMacroDefined
- handleMacroUndefined
- handleMacroReference
Update your C++ knowledge – Modern C++11/14/17 Training
Find out more