]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/clang/lib/Index/IndexingContext.cpp
Merge clang trunk r300422 and resolve conflicts.
[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 bool IndexingContext::shouldIndexFunctionLocalSymbols() const {
21   return IndexOpts.IndexFunctionLocals;
22 }
23
24 bool IndexingContext::handleDecl(const Decl *D,
25                                  SymbolRoleSet Roles,
26                                  ArrayRef<SymbolRelation> Relations) {
27   return handleDecl(D, D->getLocation(), Roles, Relations);
28 }
29
30 bool IndexingContext::handleDecl(const Decl *D, SourceLocation Loc,
31                                  SymbolRoleSet Roles,
32                                  ArrayRef<SymbolRelation> Relations,
33                                  const DeclContext *DC) {
34   if (!DC)
35     DC = D->getDeclContext();
36
37   const Decl *OrigD = D;
38   if (isa<ObjCPropertyImplDecl>(D)) {
39     D = cast<ObjCPropertyImplDecl>(D)->getPropertyDecl();
40   }
41   return handleDeclOccurrence(D, Loc, /*IsRef=*/false, cast<Decl>(DC),
42                               Roles, Relations,
43                               nullptr, OrigD, DC);
44 }
45
46 bool IndexingContext::handleReference(const NamedDecl *D, SourceLocation Loc,
47                                       const NamedDecl *Parent,
48                                       const DeclContext *DC,
49                                       SymbolRoleSet Roles,
50                                       ArrayRef<SymbolRelation> Relations,
51                                       const Expr *RefE,
52                                       const Decl *RefD) {
53   if (!shouldIndexFunctionLocalSymbols() && isFunctionLocalSymbol(D))
54     return true;
55
56   if (isa<NonTypeTemplateParmDecl>(D) || isa<TemplateTypeParmDecl>(D))
57     return true;
58     
59   return handleDeclOccurrence(D, Loc, /*IsRef=*/true, Parent, Roles, Relations,
60                               RefE, RefD, DC);
61 }
62
63 bool IndexingContext::importedModule(const ImportDecl *ImportD) {
64   SourceLocation Loc;
65   auto IdLocs = ImportD->getIdentifierLocs();
66   if (!IdLocs.empty())
67     Loc = IdLocs.front();
68   else
69     Loc = ImportD->getLocation();
70   SourceManager &SM = Ctx->getSourceManager();
71   Loc = SM.getFileLoc(Loc);
72   if (Loc.isInvalid())
73     return true;
74
75   FileID FID;
76   unsigned Offset;
77   std::tie(FID, Offset) = SM.getDecomposedLoc(Loc);
78   if (FID.isInvalid())
79     return true;
80
81   bool Invalid = false;
82   const SrcMgr::SLocEntry &SEntry = SM.getSLocEntry(FID, &Invalid);
83   if (Invalid || !SEntry.isFile())
84     return true;
85
86   if (SEntry.getFile().getFileCharacteristic() != SrcMgr::C_User) {
87     switch (IndexOpts.SystemSymbolFilter) {
88     case IndexingOptions::SystemSymbolFilterKind::None:
89       return true;
90     case IndexingOptions::SystemSymbolFilterKind::DeclarationsOnly:
91     case IndexingOptions::SystemSymbolFilterKind::All:
92       break;
93     }
94   }
95
96   SymbolRoleSet Roles = (unsigned)SymbolRole::Declaration;
97   if (ImportD->isImplicit())
98     Roles |= (unsigned)SymbolRole::Implicit;
99
100   return DataConsumer.handleModuleOccurence(ImportD, Roles, FID, Offset);
101 }
102
103 bool IndexingContext::isTemplateImplicitInstantiation(const Decl *D) {
104   TemplateSpecializationKind TKind = TSK_Undeclared;
105   if (const ClassTemplateSpecializationDecl *
106       SD = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
107     TKind = SD->getSpecializationKind();
108   } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
109     TKind = FD->getTemplateSpecializationKind();
110   } else if (auto *VD = dyn_cast<VarDecl>(D)) {
111     TKind = VD->getTemplateSpecializationKind();
112   }
113   switch (TKind) {
114     case TSK_Undeclared:
115     case TSK_ExplicitSpecialization:
116       return false;
117     case TSK_ImplicitInstantiation:
118     case TSK_ExplicitInstantiationDeclaration:
119     case TSK_ExplicitInstantiationDefinition:
120       return true;
121   }
122   llvm_unreachable("invalid TemplateSpecializationKind");
123 }
124
125 bool IndexingContext::shouldIgnoreIfImplicit(const Decl *D) {
126   if (isa<ObjCInterfaceDecl>(D))
127     return false;
128   if (isa<ObjCCategoryDecl>(D))
129     return false;
130   if (isa<ObjCIvarDecl>(D))
131     return false;
132   if (isa<ObjCMethodDecl>(D))
133     return false;
134   if (isa<ImportDecl>(D))
135     return false;
136   return true;
137 }
138
139 static const Decl *adjustTemplateImplicitInstantiation(const Decl *D) {
140   if (const ClassTemplateSpecializationDecl *
141       SD = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
142     return SD->getTemplateInstantiationPattern();
143   } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
144     return FD->getTemplateInstantiationPattern();
145   } else if (auto *VD = dyn_cast<VarDecl>(D)) {
146     return VD->getTemplateInstantiationPattern();
147   }
148   return nullptr;
149 }
150
151 static bool isDeclADefinition(const Decl *D, const DeclContext *ContainerDC, ASTContext &Ctx) {
152   if (auto VD = dyn_cast<VarDecl>(D))
153     return VD->isThisDeclarationADefinition(Ctx);
154
155   if (auto FD = dyn_cast<FunctionDecl>(D))
156     return FD->isThisDeclarationADefinition();
157
158   if (auto TD = dyn_cast<TagDecl>(D))
159     return TD->isThisDeclarationADefinition();
160
161   if (auto MD = dyn_cast<ObjCMethodDecl>(D))
162     return MD->isThisDeclarationADefinition() || isa<ObjCImplDecl>(ContainerDC);
163
164   if (isa<TypedefNameDecl>(D) ||
165       isa<EnumConstantDecl>(D) ||
166       isa<FieldDecl>(D) ||
167       isa<MSPropertyDecl>(D) ||
168       isa<ObjCImplDecl>(D) ||
169       isa<ObjCPropertyImplDecl>(D))
170     return true;
171
172   return false;
173 }
174
175 static const Decl *adjustParent(const Decl *Parent) {
176   if (!Parent)
177     return nullptr;
178   for (;; Parent = cast<Decl>(Parent->getDeclContext())) {
179     if (isa<TranslationUnitDecl>(Parent))
180       return nullptr;
181     if (isa<LinkageSpecDecl>(Parent) || isa<BlockDecl>(Parent))
182       continue;
183     if (auto NS = dyn_cast<NamespaceDecl>(Parent)) {
184       if (NS->isAnonymousNamespace())
185         continue;
186     } else if (auto RD = dyn_cast<RecordDecl>(Parent)) {
187       if (RD->isAnonymousStructOrUnion())
188         continue;
189     } else if (auto FD = dyn_cast<FieldDecl>(Parent)) {
190       if (FD->getDeclName().isEmpty())
191         continue;
192     }
193     return Parent;
194   }
195 }
196
197 static const Decl *getCanonicalDecl(const Decl *D) {
198   D = D->getCanonicalDecl();
199   if (auto TD = dyn_cast<TemplateDecl>(D)) {
200     D = TD->getTemplatedDecl();
201     assert(D->isCanonicalDecl());
202   }
203
204   return D;
205 }
206
207 static bool shouldReportOccurrenceForSystemDeclOnlyMode(
208     bool IsRef, SymbolRoleSet Roles, ArrayRef<SymbolRelation> Relations) {
209   if (!IsRef)
210     return true;
211
212   auto acceptForRelation = [](SymbolRoleSet roles) -> bool {
213     bool accept = false;
214     applyForEachSymbolRoleInterruptible(roles, [&accept](SymbolRole r) -> bool {
215       switch (r) {
216       case SymbolRole::RelationChildOf:
217       case SymbolRole::RelationBaseOf:
218       case SymbolRole::RelationOverrideOf:
219       case SymbolRole::RelationExtendedBy:
220       case SymbolRole::RelationAccessorOf:
221       case SymbolRole::RelationIBTypeOf:
222         accept = true;
223         return false;
224       case SymbolRole::Declaration:
225       case SymbolRole::Definition:
226       case SymbolRole::Reference:
227       case SymbolRole::Read:
228       case SymbolRole::Write:
229       case SymbolRole::Call:
230       case SymbolRole::Dynamic:
231       case SymbolRole::AddressOf:
232       case SymbolRole::Implicit:
233       case SymbolRole::RelationReceivedBy:
234       case SymbolRole::RelationCalledBy:
235       case SymbolRole::RelationContainedBy:
236         return true;
237       }
238       llvm_unreachable("Unsupported SymbolRole value!");
239     });
240     return accept;
241   };
242
243   for (auto &Rel : Relations) {
244     if (acceptForRelation(Rel.Roles))
245       return true;
246   }
247
248   return false;
249 }
250
251 bool IndexingContext::handleDeclOccurrence(const Decl *D, SourceLocation Loc,
252                                            bool IsRef, const Decl *Parent,
253                                            SymbolRoleSet Roles,
254                                            ArrayRef<SymbolRelation> Relations,
255                                            const Expr *OrigE,
256                                            const Decl *OrigD,
257                                            const DeclContext *ContainerDC) {
258   if (D->isImplicit() && !isa<ObjCMethodDecl>(D))
259     return true;
260   if (!isa<NamedDecl>(D) ||
261       (cast<NamedDecl>(D)->getDeclName().isEmpty() &&
262        !isa<TagDecl>(D) && !isa<ObjCCategoryDecl>(D)))
263     return true;
264
265   SourceManager &SM = Ctx->getSourceManager();
266   Loc = SM.getFileLoc(Loc);
267   if (Loc.isInvalid())
268     return true;
269
270   FileID FID;
271   unsigned Offset;
272   std::tie(FID, Offset) = SM.getDecomposedLoc(Loc);
273   if (FID.isInvalid())
274     return true;
275
276   bool Invalid = false;
277   const SrcMgr::SLocEntry &SEntry = SM.getSLocEntry(FID, &Invalid);
278   if (Invalid || !SEntry.isFile())
279     return true;
280
281   if (SEntry.getFile().getFileCharacteristic() != SrcMgr::C_User) {
282     switch (IndexOpts.SystemSymbolFilter) {
283     case IndexingOptions::SystemSymbolFilterKind::None:
284       return true;
285     case IndexingOptions::SystemSymbolFilterKind::DeclarationsOnly:
286       if (!shouldReportOccurrenceForSystemDeclOnlyMode(IsRef, Roles, Relations))
287         return true;
288       break;
289     case IndexingOptions::SystemSymbolFilterKind::All:
290       break;
291     }
292   }
293
294   if (isTemplateImplicitInstantiation(D)) {
295     if (!IsRef)
296       return true;
297     D = adjustTemplateImplicitInstantiation(D);
298     if (!D)
299       return true;
300     assert(!isTemplateImplicitInstantiation(D));
301   }
302
303   if (!OrigD)
304     OrigD = D;
305
306   if (IsRef)
307     Roles |= (unsigned)SymbolRole::Reference;
308   else if (isDeclADefinition(OrigD, ContainerDC, *Ctx))
309     Roles |= (unsigned)SymbolRole::Definition;
310   else
311     Roles |= (unsigned)SymbolRole::Declaration;
312
313   D = getCanonicalDecl(D);
314   Parent = adjustParent(Parent);
315   if (Parent)
316     Parent = getCanonicalDecl(Parent);
317
318   SmallVector<SymbolRelation, 6> FinalRelations;
319   FinalRelations.reserve(Relations.size()+1);
320
321   auto addRelation = [&](SymbolRelation Rel) {
322     auto It = std::find_if(FinalRelations.begin(), FinalRelations.end(),
323                 [&](SymbolRelation Elem)->bool {
324                   return Elem.RelatedSymbol == Rel.RelatedSymbol;
325                 });
326     if (It != FinalRelations.end()) {
327       It->Roles |= Rel.Roles;
328     } else {
329       FinalRelations.push_back(Rel);
330     }
331     Roles |= Rel.Roles;
332   };
333
334   if (Parent) {
335     if (IsRef || (!isa<ParmVarDecl>(D) && isFunctionLocalSymbol(D))) {
336       addRelation(SymbolRelation{
337         (unsigned)SymbolRole::RelationContainedBy,
338         Parent
339       });
340     } else {
341       addRelation(SymbolRelation{
342         (unsigned)SymbolRole::RelationChildOf,
343         Parent
344       });
345     }
346   }
347
348   for (auto &Rel : Relations) {
349     addRelation(SymbolRelation(Rel.Roles,
350                                Rel.RelatedSymbol->getCanonicalDecl()));
351   }
352
353   IndexDataConsumer::ASTNodeInfo Node{ OrigE, OrigD, Parent, ContainerDC };
354   return DataConsumer.handleDeclOccurence(D, Roles, FinalRelations, FID, Offset,
355                                           Node);
356 }