]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/clang/lib/Index/IndexingContext.cpp
Update clang to trunk r290819 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 handleDeclOccurrence(D, D->getLocation(), /*IsRef=*/false,
28                               cast<Decl>(D->getDeclContext()), Roles, Relations,
29                               nullptr, nullptr, D->getDeclContext());
30 }
31
32 bool IndexingContext::handleDecl(const Decl *D, SourceLocation Loc,
33                                  SymbolRoleSet Roles,
34                                  ArrayRef<SymbolRelation> Relations,
35                                  const DeclContext *DC) {
36   if (!DC)
37     DC = D->getDeclContext();
38   return handleDeclOccurrence(D, Loc, /*IsRef=*/false, cast<Decl>(DC),
39                               Roles, Relations,
40                               nullptr, nullptr, DC);
41 }
42
43 bool IndexingContext::handleReference(const NamedDecl *D, SourceLocation Loc,
44                                       const NamedDecl *Parent,
45                                       const DeclContext *DC,
46                                       SymbolRoleSet Roles,
47                                       ArrayRef<SymbolRelation> Relations,
48                                       const Expr *RefE,
49                                       const Decl *RefD) {
50   if (!shouldIndexFunctionLocalSymbols() && isFunctionLocalDecl(D))
51     return true;
52
53   if (isa<NonTypeTemplateParmDecl>(D) || isa<TemplateTypeParmDecl>(D))
54     return true;
55     
56   return handleDeclOccurrence(D, Loc, /*IsRef=*/true, Parent, Roles, Relations,
57                               RefE, RefD, DC);
58 }
59
60 bool IndexingContext::importedModule(const ImportDecl *ImportD) {
61   SourceLocation Loc;
62   auto IdLocs = ImportD->getIdentifierLocs();
63   if (!IdLocs.empty())
64     Loc = IdLocs.front();
65   else
66     Loc = ImportD->getLocation();
67   SourceManager &SM = Ctx->getSourceManager();
68   Loc = SM.getFileLoc(Loc);
69   if (Loc.isInvalid())
70     return true;
71
72   FileID FID;
73   unsigned Offset;
74   std::tie(FID, Offset) = SM.getDecomposedLoc(Loc);
75   if (FID.isInvalid())
76     return true;
77
78   bool Invalid = false;
79   const SrcMgr::SLocEntry &SEntry = SM.getSLocEntry(FID, &Invalid);
80   if (Invalid || !SEntry.isFile())
81     return true;
82
83   if (SEntry.getFile().getFileCharacteristic() != SrcMgr::C_User) {
84     switch (IndexOpts.SystemSymbolFilter) {
85     case IndexingOptions::SystemSymbolFilterKind::None:
86       return true;
87     case IndexingOptions::SystemSymbolFilterKind::DeclarationsOnly:
88     case IndexingOptions::SystemSymbolFilterKind::All:
89       break;
90     }
91   }
92
93   SymbolRoleSet Roles = (unsigned)SymbolRole::Declaration;
94   if (ImportD->isImplicit())
95     Roles |= (unsigned)SymbolRole::Implicit;
96
97   return DataConsumer.handleModuleOccurence(ImportD, Roles, FID, Offset);
98 }
99
100 bool IndexingContext::isFunctionLocalDecl(const Decl *D) {
101   assert(D);
102
103   if (isa<TemplateTemplateParmDecl>(D))
104     return true;
105
106   if (isa<ObjCTypeParamDecl>(D))
107     return true;
108
109   if (!D->getParentFunctionOrMethod())
110     return false;
111
112   if (const NamedDecl *ND = dyn_cast<NamedDecl>(D)) {
113     switch (ND->getFormalLinkage()) {
114     case NoLinkage:
115     case VisibleNoLinkage:
116     case InternalLinkage:
117       return true;
118     case UniqueExternalLinkage:
119       llvm_unreachable("Not a sema linkage");
120     case ExternalLinkage:
121       return false;
122     }
123   }
124
125   return true;
126 }
127
128 bool IndexingContext::isTemplateImplicitInstantiation(const Decl *D) {
129   TemplateSpecializationKind TKind = TSK_Undeclared;
130   if (const ClassTemplateSpecializationDecl *
131       SD = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
132     TKind = SD->getSpecializationKind();
133   } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
134     TKind = FD->getTemplateSpecializationKind();
135   } else if (auto *VD = dyn_cast<VarDecl>(D)) {
136     TKind = VD->getTemplateSpecializationKind();
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 Decl *adjustTemplateImplicitInstantiation(const Decl *D) {
165   if (const ClassTemplateSpecializationDecl *
166       SD = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
167     return SD->getTemplateInstantiationPattern();
168   } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
169     return FD->getTemplateInstantiationPattern();
170   } else if (auto *VD = dyn_cast<VarDecl>(D)) {
171     return VD->getTemplateInstantiationPattern();
172   }
173   return nullptr;
174 }
175
176 static bool isDeclADefinition(const Decl *D, const DeclContext *ContainerDC, ASTContext &Ctx) {
177   if (auto VD = dyn_cast<VarDecl>(D))
178     return VD->isThisDeclarationADefinition(Ctx);
179
180   if (auto FD = dyn_cast<FunctionDecl>(D))
181     return FD->isThisDeclarationADefinition();
182
183   if (auto TD = dyn_cast<TagDecl>(D))
184     return TD->isThisDeclarationADefinition();
185
186   if (auto MD = dyn_cast<ObjCMethodDecl>(D))
187     return MD->isThisDeclarationADefinition() || isa<ObjCImplDecl>(ContainerDC);
188
189   if (isa<TypedefNameDecl>(D) ||
190       isa<EnumConstantDecl>(D) ||
191       isa<FieldDecl>(D) ||
192       isa<MSPropertyDecl>(D) ||
193       isa<ObjCImplDecl>(D) ||
194       isa<ObjCPropertyImplDecl>(D))
195     return true;
196
197   return false;
198 }
199
200 static const Decl *adjustParent(const Decl *Parent) {
201   if (!Parent)
202     return nullptr;
203   for (;; Parent = cast<Decl>(Parent->getDeclContext())) {
204     if (isa<TranslationUnitDecl>(Parent))
205       return nullptr;
206     if (isa<LinkageSpecDecl>(Parent) || isa<BlockDecl>(Parent))
207       continue;
208     if (auto NS = dyn_cast<NamespaceDecl>(Parent)) {
209       if (NS->isAnonymousNamespace())
210         continue;
211     } else if (auto RD = dyn_cast<RecordDecl>(Parent)) {
212       if (RD->isAnonymousStructOrUnion())
213         continue;
214     } else if (auto FD = dyn_cast<FieldDecl>(Parent)) {
215       if (FD->getDeclName().isEmpty())
216         continue;
217     }
218     return Parent;
219   }
220 }
221
222 static const Decl *getCanonicalDecl(const Decl *D) {
223   D = D->getCanonicalDecl();
224   if (auto TD = dyn_cast<TemplateDecl>(D)) {
225     D = TD->getTemplatedDecl();
226     assert(D->isCanonicalDecl());
227   }
228
229   return D;
230 }
231
232 bool IndexingContext::handleDeclOccurrence(const Decl *D, SourceLocation Loc,
233                                            bool IsRef, const Decl *Parent,
234                                            SymbolRoleSet Roles,
235                                            ArrayRef<SymbolRelation> Relations,
236                                            const Expr *OrigE,
237                                            const Decl *OrigD,
238                                            const DeclContext *ContainerDC) {
239   if (D->isImplicit() && !isa<ObjCMethodDecl>(D))
240     return true;
241   if (!isa<NamedDecl>(D) ||
242       (cast<NamedDecl>(D)->getDeclName().isEmpty() &&
243        !isa<TagDecl>(D) && !isa<ObjCCategoryDecl>(D)))
244     return true;
245
246   SourceManager &SM = Ctx->getSourceManager();
247   Loc = SM.getFileLoc(Loc);
248   if (Loc.isInvalid())
249     return true;
250
251   FileID FID;
252   unsigned Offset;
253   std::tie(FID, Offset) = SM.getDecomposedLoc(Loc);
254   if (FID.isInvalid())
255     return true;
256
257   bool Invalid = false;
258   const SrcMgr::SLocEntry &SEntry = SM.getSLocEntry(FID, &Invalid);
259   if (Invalid || !SEntry.isFile())
260     return true;
261
262   if (SEntry.getFile().getFileCharacteristic() != SrcMgr::C_User) {
263     switch (IndexOpts.SystemSymbolFilter) {
264     case IndexingOptions::SystemSymbolFilterKind::None:
265       return true;
266     case IndexingOptions::SystemSymbolFilterKind::DeclarationsOnly:
267       if (IsRef)
268         return true;
269       break;
270     case IndexingOptions::SystemSymbolFilterKind::All:
271       break;
272     }
273   }
274
275   if (isTemplateImplicitInstantiation(D)) {
276     if (!IsRef)
277       return true;
278     D = adjustTemplateImplicitInstantiation(D);
279     if (!D)
280       return true;
281     assert(!isTemplateImplicitInstantiation(D));
282   }
283
284   if (!OrigD)
285     OrigD = D;
286
287   if (IsRef)
288     Roles |= (unsigned)SymbolRole::Reference;
289   else if (isDeclADefinition(D, ContainerDC, *Ctx))
290     Roles |= (unsigned)SymbolRole::Definition;
291   else
292     Roles |= (unsigned)SymbolRole::Declaration;
293
294   D = getCanonicalDecl(D);
295   Parent = adjustParent(Parent);
296   if (Parent)
297     Parent = getCanonicalDecl(Parent);
298
299   SmallVector<SymbolRelation, 6> FinalRelations;
300   FinalRelations.reserve(Relations.size()+1);
301
302   auto addRelation = [&](SymbolRelation Rel) {
303     auto It = std::find_if(FinalRelations.begin(), FinalRelations.end(),
304                 [&](SymbolRelation Elem)->bool {
305                   return Elem.RelatedSymbol == Rel.RelatedSymbol;
306                 });
307     if (It != FinalRelations.end()) {
308       It->Roles |= Rel.Roles;
309     } else {
310       FinalRelations.push_back(Rel);
311     }
312     Roles |= Rel.Roles;
313   };
314
315   if (!IsRef && Parent && !cast<DeclContext>(Parent)->isFunctionOrMethod()) {
316     addRelation(SymbolRelation{(unsigned)SymbolRole::RelationChildOf, Parent});
317   }
318   for (auto &Rel : Relations) {
319     addRelation(SymbolRelation(Rel.Roles,
320                                Rel.RelatedSymbol->getCanonicalDecl()));
321   }
322
323   IndexDataConsumer::ASTNodeInfo Node{ OrigE, OrigD, Parent, ContainerDC };
324   return DataConsumer.handleDeclOccurence(D, Roles, FinalRelations, FID, Offset,
325                                           Node);
326 }