]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/clang/lib/Index/IndexingContext.cpp
Merge llvm, clang, lld, lldb, compiler-rt and libc++ r304460, and update
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / clang / lib / Index / IndexingContext.cpp
1 //===- IndexingContext.cpp - Indexing context data ------------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #include "IndexingContext.h"
11 #include "clang/Index/IndexDataConsumer.h"
12 #include "clang/AST/ASTContext.h"
13 #include "clang/AST/DeclTemplate.h"
14 #include "clang/AST/DeclObjC.h"
15 #include "clang/Basic/SourceManager.h"
16
17 using namespace clang;
18 using namespace index;
19
20 static bool isGeneratedDecl(const Decl *D) {
21   if (auto *attr = D->getAttr<ExternalSourceSymbolAttr>()) {
22     return attr->getGeneratedDeclaration();
23   }
24   return false;
25 }
26
27 bool IndexingContext::shouldIndex(const Decl *D) {
28   return !isGeneratedDecl(D);
29 }
30
31 const LangOptions &IndexingContext::getLangOpts() const {
32   return Ctx->getLangOpts();
33 }
34
35 bool IndexingContext::shouldIndexFunctionLocalSymbols() const {
36   return IndexOpts.IndexFunctionLocals;
37 }
38
39 bool IndexingContext::handleDecl(const Decl *D,
40                                  SymbolRoleSet Roles,
41                                  ArrayRef<SymbolRelation> Relations) {
42   return handleDecl(D, D->getLocation(), Roles, Relations);
43 }
44
45 bool IndexingContext::handleDecl(const Decl *D, SourceLocation Loc,
46                                  SymbolRoleSet Roles,
47                                  ArrayRef<SymbolRelation> Relations,
48                                  const DeclContext *DC) {
49   if (!DC)
50     DC = D->getDeclContext();
51
52   const Decl *OrigD = D;
53   if (isa<ObjCPropertyImplDecl>(D)) {
54     D = cast<ObjCPropertyImplDecl>(D)->getPropertyDecl();
55   }
56   return handleDeclOccurrence(D, Loc, /*IsRef=*/false, cast<Decl>(DC),
57                               Roles, Relations,
58                               nullptr, OrigD, DC);
59 }
60
61 bool IndexingContext::handleReference(const NamedDecl *D, SourceLocation Loc,
62                                       const NamedDecl *Parent,
63                                       const DeclContext *DC,
64                                       SymbolRoleSet Roles,
65                                       ArrayRef<SymbolRelation> Relations,
66                                       const Expr *RefE,
67                                       const Decl *RefD) {
68   if (!shouldIndexFunctionLocalSymbols() && isFunctionLocalSymbol(D))
69     return true;
70
71   if (isa<NonTypeTemplateParmDecl>(D) || isa<TemplateTypeParmDecl>(D))
72     return true;
73     
74   return handleDeclOccurrence(D, Loc, /*IsRef=*/true, Parent, Roles, Relations,
75                               RefE, RefD, DC);
76 }
77
78 bool IndexingContext::importedModule(const ImportDecl *ImportD) {
79   SourceLocation Loc;
80   auto IdLocs = ImportD->getIdentifierLocs();
81   if (!IdLocs.empty())
82     Loc = IdLocs.front();
83   else
84     Loc = ImportD->getLocation();
85   SourceManager &SM = Ctx->getSourceManager();
86   Loc = SM.getFileLoc(Loc);
87   if (Loc.isInvalid())
88     return true;
89
90   FileID FID;
91   unsigned Offset;
92   std::tie(FID, Offset) = SM.getDecomposedLoc(Loc);
93   if (FID.isInvalid())
94     return true;
95
96   bool Invalid = false;
97   const SrcMgr::SLocEntry &SEntry = SM.getSLocEntry(FID, &Invalid);
98   if (Invalid || !SEntry.isFile())
99     return true;
100
101   if (SEntry.getFile().getFileCharacteristic() != SrcMgr::C_User) {
102     switch (IndexOpts.SystemSymbolFilter) {
103     case IndexingOptions::SystemSymbolFilterKind::None:
104       return true;
105     case IndexingOptions::SystemSymbolFilterKind::DeclarationsOnly:
106     case IndexingOptions::SystemSymbolFilterKind::All:
107       break;
108     }
109   }
110
111   SymbolRoleSet Roles = (unsigned)SymbolRole::Declaration;
112   if (ImportD->isImplicit())
113     Roles |= (unsigned)SymbolRole::Implicit;
114
115   return DataConsumer.handleModuleOccurence(ImportD, Roles, FID, Offset);
116 }
117
118 bool IndexingContext::isTemplateImplicitInstantiation(const Decl *D) {
119   TemplateSpecializationKind TKind = TSK_Undeclared;
120   if (const ClassTemplateSpecializationDecl *
121       SD = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
122     TKind = SD->getSpecializationKind();
123   } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
124     TKind = FD->getTemplateSpecializationKind();
125   } else if (auto *VD = dyn_cast<VarDecl>(D)) {
126     TKind = VD->getTemplateSpecializationKind();
127   } else if (const auto *RD = dyn_cast<CXXRecordDecl>(D)) {
128     if (RD->getInstantiatedFromMemberClass())
129       TKind = RD->getTemplateSpecializationKind();
130   } else if (const auto *ED = dyn_cast<EnumDecl>(D)) {
131     if (ED->getInstantiatedFromMemberEnum())
132       TKind = ED->getTemplateSpecializationKind();
133   } else if (isa<FieldDecl>(D) || isa<TypedefNameDecl>(D) ||
134              isa<EnumConstantDecl>(D)) {
135     if (const auto *Parent = dyn_cast<Decl>(D->getDeclContext()))
136       return isTemplateImplicitInstantiation(Parent);
137   }
138   switch (TKind) {
139     case TSK_Undeclared:
140     case TSK_ExplicitSpecialization:
141       return false;
142     case TSK_ImplicitInstantiation:
143     case TSK_ExplicitInstantiationDeclaration:
144     case TSK_ExplicitInstantiationDefinition:
145       return true;
146   }
147   llvm_unreachable("invalid TemplateSpecializationKind");
148 }
149
150 bool IndexingContext::shouldIgnoreIfImplicit(const Decl *D) {
151   if (isa<ObjCInterfaceDecl>(D))
152     return false;
153   if (isa<ObjCCategoryDecl>(D))
154     return false;
155   if (isa<ObjCIvarDecl>(D))
156     return false;
157   if (isa<ObjCMethodDecl>(D))
158     return false;
159   if (isa<ImportDecl>(D))
160     return false;
161   return true;
162 }
163
164 static const CXXRecordDecl *
165 getDeclContextForTemplateInstationPattern(const Decl *D) {
166   if (const auto *CTSD =
167           dyn_cast<ClassTemplateSpecializationDecl>(D->getDeclContext()))
168     return CTSD->getTemplateInstantiationPattern();
169   else if (const auto *RD = dyn_cast<CXXRecordDecl>(D->getDeclContext()))
170     return RD->getInstantiatedFromMemberClass();
171   return nullptr;
172 }
173
174 static const Decl *adjustTemplateImplicitInstantiation(const Decl *D) {
175   if (const ClassTemplateSpecializationDecl *
176       SD = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
177     return SD->getTemplateInstantiationPattern();
178   } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
179     return FD->getTemplateInstantiationPattern();
180   } else if (auto *VD = dyn_cast<VarDecl>(D)) {
181     return VD->getTemplateInstantiationPattern();
182   } else if (const auto *RD = dyn_cast<CXXRecordDecl>(D)) {
183     return RD->getInstantiatedFromMemberClass();
184   } else if (const auto *ED = dyn_cast<EnumDecl>(D)) {
185     return ED->getInstantiatedFromMemberEnum();
186   } else if (isa<FieldDecl>(D) || isa<TypedefNameDecl>(D)) {
187     const auto *ND = cast<NamedDecl>(D);
188     if (const CXXRecordDecl *Pattern =
189             getDeclContextForTemplateInstationPattern(ND)) {
190       for (const NamedDecl *BaseND : Pattern->lookup(ND->getDeclName())) {
191         if (BaseND->isImplicit())
192           continue;
193         if (BaseND->getKind() == ND->getKind())
194           return BaseND;
195       }
196     }
197   } else if (const auto *ECD = dyn_cast<EnumConstantDecl>(D)) {
198     if (const auto *ED = dyn_cast<EnumDecl>(ECD->getDeclContext())) {
199       if (const EnumDecl *Pattern = ED->getInstantiatedFromMemberEnum()) {
200         for (const NamedDecl *BaseECD : Pattern->lookup(ECD->getDeclName()))
201           return BaseECD;
202       }
203     }
204   }
205   return nullptr;
206 }
207
208 static bool isDeclADefinition(const Decl *D, const DeclContext *ContainerDC, ASTContext &Ctx) {
209   if (auto VD = dyn_cast<VarDecl>(D))
210     return VD->isThisDeclarationADefinition(Ctx);
211
212   if (auto FD = dyn_cast<FunctionDecl>(D))
213     return FD->isThisDeclarationADefinition();
214
215   if (auto TD = dyn_cast<TagDecl>(D))
216     return TD->isThisDeclarationADefinition();
217
218   if (auto MD = dyn_cast<ObjCMethodDecl>(D))
219     return MD->isThisDeclarationADefinition() || isa<ObjCImplDecl>(ContainerDC);
220
221   if (isa<TypedefNameDecl>(D) ||
222       isa<EnumConstantDecl>(D) ||
223       isa<FieldDecl>(D) ||
224       isa<MSPropertyDecl>(D) ||
225       isa<ObjCImplDecl>(D) ||
226       isa<ObjCPropertyImplDecl>(D))
227     return true;
228
229   return false;
230 }
231
232 static const Decl *adjustParent(const Decl *Parent) {
233   if (!Parent)
234     return nullptr;
235   for (;; Parent = cast<Decl>(Parent->getDeclContext())) {
236     if (isa<TranslationUnitDecl>(Parent))
237       return nullptr;
238     if (isa<LinkageSpecDecl>(Parent) || isa<BlockDecl>(Parent))
239       continue;
240     if (auto NS = dyn_cast<NamespaceDecl>(Parent)) {
241       if (NS->isAnonymousNamespace())
242         continue;
243     } else if (auto RD = dyn_cast<RecordDecl>(Parent)) {
244       if (RD->isAnonymousStructOrUnion())
245         continue;
246     } else if (auto FD = dyn_cast<FieldDecl>(Parent)) {
247       if (FD->getDeclName().isEmpty())
248         continue;
249     }
250     return Parent;
251   }
252 }
253
254 static const Decl *getCanonicalDecl(const Decl *D) {
255   D = D->getCanonicalDecl();
256   if (auto TD = dyn_cast<TemplateDecl>(D)) {
257     D = TD->getTemplatedDecl();
258     assert(D->isCanonicalDecl());
259   }
260
261   return D;
262 }
263
264 static bool shouldReportOccurrenceForSystemDeclOnlyMode(
265     bool IsRef, SymbolRoleSet Roles, ArrayRef<SymbolRelation> Relations) {
266   if (!IsRef)
267     return true;
268
269   auto acceptForRelation = [](SymbolRoleSet roles) -> bool {
270     bool accept = false;
271     applyForEachSymbolRoleInterruptible(roles, [&accept](SymbolRole r) -> bool {
272       switch (r) {
273       case SymbolRole::RelationChildOf:
274       case SymbolRole::RelationBaseOf:
275       case SymbolRole::RelationOverrideOf:
276       case SymbolRole::RelationExtendedBy:
277       case SymbolRole::RelationAccessorOf:
278       case SymbolRole::RelationIBTypeOf:
279         accept = true;
280         return false;
281       case SymbolRole::Declaration:
282       case SymbolRole::Definition:
283       case SymbolRole::Reference:
284       case SymbolRole::Read:
285       case SymbolRole::Write:
286       case SymbolRole::Call:
287       case SymbolRole::Dynamic:
288       case SymbolRole::AddressOf:
289       case SymbolRole::Implicit:
290       case SymbolRole::RelationReceivedBy:
291       case SymbolRole::RelationCalledBy:
292       case SymbolRole::RelationContainedBy:
293       case SymbolRole::RelationSpecializationOf:
294         return true;
295       }
296       llvm_unreachable("Unsupported SymbolRole value!");
297     });
298     return accept;
299   };
300
301   for (auto &Rel : Relations) {
302     if (acceptForRelation(Rel.Roles))
303       return true;
304   }
305
306   return false;
307 }
308
309 bool IndexingContext::handleDeclOccurrence(const Decl *D, SourceLocation Loc,
310                                            bool IsRef, const Decl *Parent,
311                                            SymbolRoleSet Roles,
312                                            ArrayRef<SymbolRelation> Relations,
313                                            const Expr *OrigE,
314                                            const Decl *OrigD,
315                                            const DeclContext *ContainerDC) {
316   if (D->isImplicit() && !isa<ObjCMethodDecl>(D))
317     return true;
318   if (!isa<NamedDecl>(D) ||
319       (cast<NamedDecl>(D)->getDeclName().isEmpty() &&
320        !isa<TagDecl>(D) && !isa<ObjCCategoryDecl>(D)))
321     return true;
322
323   SourceManager &SM = Ctx->getSourceManager();
324   Loc = SM.getFileLoc(Loc);
325   if (Loc.isInvalid())
326     return true;
327
328   FileID FID;
329   unsigned Offset;
330   std::tie(FID, Offset) = SM.getDecomposedLoc(Loc);
331   if (FID.isInvalid())
332     return true;
333
334   bool Invalid = false;
335   const SrcMgr::SLocEntry &SEntry = SM.getSLocEntry(FID, &Invalid);
336   if (Invalid || !SEntry.isFile())
337     return true;
338
339   if (SEntry.getFile().getFileCharacteristic() != SrcMgr::C_User) {
340     switch (IndexOpts.SystemSymbolFilter) {
341     case IndexingOptions::SystemSymbolFilterKind::None:
342       return true;
343     case IndexingOptions::SystemSymbolFilterKind::DeclarationsOnly:
344       if (!shouldReportOccurrenceForSystemDeclOnlyMode(IsRef, Roles, Relations))
345         return true;
346       break;
347     case IndexingOptions::SystemSymbolFilterKind::All:
348       break;
349     }
350   }
351
352   if (isTemplateImplicitInstantiation(D)) {
353     if (!IsRef)
354       return true;
355     D = adjustTemplateImplicitInstantiation(D);
356     if (!D)
357       return true;
358     assert(!isTemplateImplicitInstantiation(D));
359   }
360
361   if (!OrigD)
362     OrigD = D;
363
364   if (IsRef)
365     Roles |= (unsigned)SymbolRole::Reference;
366   else if (isDeclADefinition(OrigD, ContainerDC, *Ctx))
367     Roles |= (unsigned)SymbolRole::Definition;
368   else
369     Roles |= (unsigned)SymbolRole::Declaration;
370
371   D = getCanonicalDecl(D);
372   Parent = adjustParent(Parent);
373   if (Parent)
374     Parent = getCanonicalDecl(Parent);
375
376   SmallVector<SymbolRelation, 6> FinalRelations;
377   FinalRelations.reserve(Relations.size()+1);
378
379   auto addRelation = [&](SymbolRelation Rel) {
380     auto It = std::find_if(FinalRelations.begin(), FinalRelations.end(),
381                 [&](SymbolRelation Elem)->bool {
382                   return Elem.RelatedSymbol == Rel.RelatedSymbol;
383                 });
384     if (It != FinalRelations.end()) {
385       It->Roles |= Rel.Roles;
386     } else {
387       FinalRelations.push_back(Rel);
388     }
389     Roles |= Rel.Roles;
390   };
391
392   if (Parent) {
393     if (IsRef || (!isa<ParmVarDecl>(D) && isFunctionLocalSymbol(D))) {
394       addRelation(SymbolRelation{
395         (unsigned)SymbolRole::RelationContainedBy,
396         Parent
397       });
398     } else {
399       addRelation(SymbolRelation{
400         (unsigned)SymbolRole::RelationChildOf,
401         Parent
402       });
403     }
404   }
405
406   for (auto &Rel : Relations) {
407     addRelation(SymbolRelation(Rel.Roles,
408                                Rel.RelatedSymbol->getCanonicalDecl()));
409   }
410
411   IndexDataConsumer::ASTNodeInfo Node{ OrigE, OrigD, Parent, ContainerDC };
412   return DataConsumer.handleDeclOccurence(D, Roles, FinalRelations, FID, Offset,
413                                           Node);
414 }