]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/clang/lib/Index/IndexDecl.cpp
Merge ^/head r314178 through r314269.
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / clang / lib / Index / IndexDecl.cpp
1 //===- IndexDecl.cpp - Indexing declarations ------------------------------===//
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/DeclVisitor.h"
13
14 using namespace clang;
15 using namespace index;
16
17 #define TRY_TO(CALL_EXPR)                                                      \
18   do {                                                                         \
19     if (!CALL_EXPR)                                                            \
20       return false;                                                            \
21   } while (0)
22
23 namespace {
24
25 class IndexingDeclVisitor : public ConstDeclVisitor<IndexingDeclVisitor, bool> {
26   IndexingContext &IndexCtx;
27
28 public:
29   explicit IndexingDeclVisitor(IndexingContext &indexCtx)
30     : IndexCtx(indexCtx) { }
31
32   bool Handled = true;
33
34   bool VisitDecl(const Decl *D) {
35     Handled = false;
36     return true;
37   }
38
39   /// \brief Returns true if the given method has been defined explicitly by the
40   /// user.
41   static bool hasUserDefined(const ObjCMethodDecl *D,
42                              const ObjCImplDecl *Container) {
43     const ObjCMethodDecl *MD = Container->getMethod(D->getSelector(),
44                                                     D->isInstanceMethod());
45     return MD && !MD->isImplicit() && MD->isThisDeclarationADefinition();
46   }
47
48   void handleDeclarator(const DeclaratorDecl *D,
49                         const NamedDecl *Parent = nullptr,
50                         bool isIBType = false) {
51     if (!Parent) Parent = D;
52
53     IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), Parent,
54                                  Parent->getLexicalDeclContext(),
55                                  /*isBase=*/false, isIBType);
56     IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent);
57     if (IndexCtx.shouldIndexFunctionLocalSymbols()) {
58       // Only index parameters in definitions, parameters in declarations are
59       // not useful.
60       if (const ParmVarDecl *Parm = dyn_cast<ParmVarDecl>(D)) {
61         auto *DC = Parm->getDeclContext();
62         if (auto *FD = dyn_cast<FunctionDecl>(DC)) {
63           if (FD->isThisDeclarationADefinition())
64             IndexCtx.handleDecl(Parm);
65         } else if (auto *MD = dyn_cast<ObjCMethodDecl>(DC)) {
66           if (MD->isThisDeclarationADefinition())
67             IndexCtx.handleDecl(Parm);
68         } else {
69           IndexCtx.handleDecl(Parm);
70         }
71       } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
72         if (FD->isThisDeclarationADefinition()) {
73           for (auto PI : FD->parameters()) {
74             IndexCtx.handleDecl(PI);
75           }
76         }
77       }
78     }
79   }
80
81   bool handleObjCMethod(const ObjCMethodDecl *D,
82                         const ObjCPropertyDecl *AssociatedProp = nullptr) {
83     SmallVector<SymbolRelation, 4> Relations;
84     SmallVector<const ObjCMethodDecl*, 4> Overriden;
85
86     D->getOverriddenMethods(Overriden);
87     for(auto overridden: Overriden) {
88       Relations.emplace_back((unsigned) SymbolRole::RelationOverrideOf,
89                              overridden);
90     }
91     if (AssociatedProp)
92       Relations.emplace_back((unsigned)SymbolRole::RelationAccessorOf,
93                              AssociatedProp);
94
95     // getLocation() returns beginning token of a method declaration, but for
96     // indexing purposes we want to point to the base name.
97     SourceLocation MethodLoc = D->getSelectorStartLoc();
98     if (MethodLoc.isInvalid())
99       MethodLoc = D->getLocation();
100
101     if (!IndexCtx.handleDecl(D, MethodLoc, (unsigned)SymbolRole::Dynamic, Relations))
102       return false;
103     IndexCtx.indexTypeSourceInfo(D->getReturnTypeSourceInfo(), D);
104     bool hasIBActionAndFirst = D->hasAttr<IBActionAttr>();
105     for (const auto *I : D->parameters()) {
106       handleDeclarator(I, D, /*isIBType=*/hasIBActionAndFirst);
107       hasIBActionAndFirst = false;
108     }
109
110     if (D->isThisDeclarationADefinition()) {
111       const Stmt *Body = D->getBody();
112       if (Body) {
113         IndexCtx.indexBody(Body, D, D);
114       }
115     }
116     return true;
117   }
118
119   bool VisitFunctionDecl(const FunctionDecl *D) {
120     if (D->isDeleted())
121       return true;
122
123     SymbolRoleSet Roles{};
124     SmallVector<SymbolRelation, 4> Relations;
125     if (auto *CXXMD = dyn_cast<CXXMethodDecl>(D)) {
126       if (CXXMD->isVirtual())
127         Roles |= (unsigned)SymbolRole::Dynamic;
128       for (auto I = CXXMD->begin_overridden_methods(),
129            E = CXXMD->end_overridden_methods(); I != E; ++I) {
130         Relations.emplace_back((unsigned)SymbolRole::RelationOverrideOf, *I);
131       }
132     }
133
134     if (!IndexCtx.handleDecl(D, Roles, Relations))
135       return false;
136     handleDeclarator(D);
137
138     if (const CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(D)) {
139       // Constructor initializers.
140       for (const auto *Init : Ctor->inits()) {
141         if (Init->isWritten()) {
142           IndexCtx.indexTypeSourceInfo(Init->getTypeSourceInfo(), D);
143           if (const FieldDecl *Member = Init->getAnyMember())
144             IndexCtx.handleReference(Member, Init->getMemberLocation(), D, D,
145                                      (unsigned)SymbolRole::Write);
146           IndexCtx.indexBody(Init->getInit(), D, D);
147         }
148       }
149     }
150
151     if (D->isThisDeclarationADefinition()) {
152       const Stmt *Body = D->getBody();
153       if (Body) {
154         IndexCtx.indexBody(Body, D, D);
155       }
156     }
157     return true;
158   }
159
160   bool VisitVarDecl(const VarDecl *D) {
161     if (!IndexCtx.handleDecl(D))
162       return false;
163     handleDeclarator(D);
164     IndexCtx.indexBody(D->getInit(), D);
165     return true;
166   }
167
168   bool VisitFieldDecl(const FieldDecl *D) {
169     if (!IndexCtx.handleDecl(D))
170       return false;
171     handleDeclarator(D);
172     if (D->isBitField())
173       IndexCtx.indexBody(D->getBitWidth(), D);
174     else if (D->hasInClassInitializer())
175       IndexCtx.indexBody(D->getInClassInitializer(), D);
176     return true;
177   }
178
179   bool VisitObjCIvarDecl(const ObjCIvarDecl *D) {
180     if (D->getSynthesize()) {
181       // For synthesized ivars, use the location of the ObjC implementation,
182       // not the location of the property.
183       // Otherwise the header file containing the @interface will have different
184       // indexing contents based on whether the @implementation was present or
185       // not in the translation unit.
186       return IndexCtx.handleDecl(D,
187                                  cast<Decl>(D->getDeclContext())->getLocation(),
188                                  (unsigned)SymbolRole::Implicit);
189     }
190     if (!IndexCtx.handleDecl(D))
191       return false;
192     handleDeclarator(D);
193     return true;
194   }
195
196   bool VisitMSPropertyDecl(const MSPropertyDecl *D) {
197     handleDeclarator(D);
198     return true;
199   }
200
201   bool VisitEnumConstantDecl(const EnumConstantDecl *D) {
202     if (!IndexCtx.handleDecl(D))
203       return false;
204     IndexCtx.indexBody(D->getInitExpr(), D);
205     return true;
206   }
207
208   bool VisitTypedefNameDecl(const TypedefNameDecl *D) {
209     if (!IndexCtx.handleDecl(D))
210       return false;
211     IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D);
212     return true;
213   }
214
215   bool VisitTagDecl(const TagDecl *D) {
216     // Non-free standing tags are handled in indexTypeSourceInfo.
217     if (D->isFreeStanding()) {
218       if (D->isThisDeclarationADefinition()) {
219         IndexCtx.indexTagDecl(D);
220       } else {
221         auto *Parent = dyn_cast<NamedDecl>(D->getDeclContext());
222         return IndexCtx.handleReference(D, D->getLocation(), Parent,
223                                         D->getLexicalDeclContext(),
224                                         SymbolRoleSet());
225       }
226     }
227     return true;
228   }
229
230   bool handleReferencedProtocols(const ObjCProtocolList &ProtList,
231                                  const ObjCContainerDecl *ContD) {
232     ObjCInterfaceDecl::protocol_loc_iterator LI = ProtList.loc_begin();
233     for (ObjCInterfaceDecl::protocol_iterator
234          I = ProtList.begin(), E = ProtList.end(); I != E; ++I, ++LI) {
235       SourceLocation Loc = *LI;
236       ObjCProtocolDecl *PD = *I;
237       TRY_TO(IndexCtx.handleReference(PD, Loc, ContD, ContD,
238           SymbolRoleSet(),
239           SymbolRelation{(unsigned)SymbolRole::RelationBaseOf, ContD}));
240     }
241     return true;
242   }
243
244   bool VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D) {
245     if (D->isThisDeclarationADefinition()) {
246       TRY_TO(IndexCtx.handleDecl(D));
247       if (auto *SuperD = D->getSuperClass()) {
248         TRY_TO(IndexCtx.handleReference(SuperD, D->getSuperClassLoc(), D, D,
249             SymbolRoleSet(),
250             SymbolRelation{(unsigned)SymbolRole::RelationBaseOf, D}));
251       }
252       TRY_TO(handleReferencedProtocols(D->getReferencedProtocols(), D));
253       TRY_TO(IndexCtx.indexDeclContext(D));
254     } else {
255       return IndexCtx.handleReference(D, D->getLocation(), nullptr,
256                                       D->getDeclContext(), SymbolRoleSet());
257     }
258     return true;
259   }
260
261   bool VisitObjCProtocolDecl(const ObjCProtocolDecl *D) {
262     if (D->isThisDeclarationADefinition()) {
263       TRY_TO(IndexCtx.handleDecl(D));
264       TRY_TO(handleReferencedProtocols(D->getReferencedProtocols(), D));
265       TRY_TO(IndexCtx.indexDeclContext(D));
266     } else {
267       return IndexCtx.handleReference(D, D->getLocation(), nullptr,
268                                       D->getDeclContext(), SymbolRoleSet());
269     }
270     return true;
271   }
272
273   bool VisitObjCImplementationDecl(const ObjCImplementationDecl *D) {
274     const ObjCInterfaceDecl *Class = D->getClassInterface();
275     if (!Class)
276       return true;
277
278     if (Class->isImplicitInterfaceDecl())
279       IndexCtx.handleDecl(Class);
280
281     if (!IndexCtx.handleDecl(D))
282       return false;
283
284     // Index the ivars first to make sure the synthesized ivars are indexed
285     // before indexing the methods that can reference them.
286     for (const auto *IvarI : D->ivars())
287       IndexCtx.indexDecl(IvarI);
288     for (const auto *I : D->decls()) {
289       if (!isa<ObjCIvarDecl>(I))
290         IndexCtx.indexDecl(I);
291     }
292
293     return true;
294   }
295
296   bool VisitObjCCategoryDecl(const ObjCCategoryDecl *D) {
297     const ObjCInterfaceDecl *C = D->getClassInterface();
298     if (!C)
299       return true;
300     TRY_TO(IndexCtx.handleReference(C, D->getLocation(), D, D, SymbolRoleSet(),
301                                    SymbolRelation{
302                                      (unsigned)SymbolRole::RelationExtendedBy, D
303                                    }));
304     SourceLocation CategoryLoc = D->getCategoryNameLoc();
305     if (!CategoryLoc.isValid())
306       CategoryLoc = D->getLocation();
307     TRY_TO(IndexCtx.handleDecl(D, CategoryLoc));
308     TRY_TO(handleReferencedProtocols(D->getReferencedProtocols(), D));
309     TRY_TO(IndexCtx.indexDeclContext(D));
310     return true;
311   }
312
313   bool VisitObjCCategoryImplDecl(const ObjCCategoryImplDecl *D) {
314     const ObjCCategoryDecl *Cat = D->getCategoryDecl();
315     if (!Cat)
316       return true;
317     const ObjCInterfaceDecl *C = D->getClassInterface();
318     if (C)
319       TRY_TO(IndexCtx.handleReference(C, D->getLocation(), D, D,
320                                       SymbolRoleSet()));
321     SourceLocation CategoryLoc = D->getCategoryNameLoc();
322     if (!CategoryLoc.isValid())
323       CategoryLoc = D->getLocation();
324     if (!IndexCtx.handleDecl(D, CategoryLoc))
325       return false;
326     IndexCtx.indexDeclContext(D);
327     return true;
328   }
329
330   bool VisitObjCMethodDecl(const ObjCMethodDecl *D) {
331     // Methods associated with a property, even user-declared ones, are
332     // handled when we handle the property.
333     if (D->isPropertyAccessor())
334       return true;
335
336     handleObjCMethod(D);
337     return true;
338   }
339
340   bool VisitObjCPropertyDecl(const ObjCPropertyDecl *D) {
341     if (ObjCMethodDecl *MD = D->getGetterMethodDecl())
342       if (MD->getLexicalDeclContext() == D->getLexicalDeclContext())
343         handleObjCMethod(MD, D);
344     if (ObjCMethodDecl *MD = D->getSetterMethodDecl())
345       if (MD->getLexicalDeclContext() == D->getLexicalDeclContext())
346         handleObjCMethod(MD, D);
347     if (!IndexCtx.handleDecl(D))
348       return false;
349     if (IBOutletCollectionAttr *attr = D->getAttr<IBOutletCollectionAttr>())
350       IndexCtx.indexTypeSourceInfo(attr->getInterfaceLoc(), D,
351                                    D->getLexicalDeclContext(), false, true);
352     IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D);
353     return true;
354   }
355
356   bool VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D) {
357     ObjCPropertyDecl *PD = D->getPropertyDecl();
358     if (!IndexCtx.handleReference(PD, D->getLocation(),
359                              /*Parent=*/cast<NamedDecl>(D->getDeclContext()),
360                              D->getDeclContext(), SymbolRoleSet(), {},
361                              /*RefE=*/nullptr, D))
362       return false;
363
364     if (D->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic)
365       return true;
366     assert(D->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize);
367     
368     if (ObjCIvarDecl *IvarD = D->getPropertyIvarDecl()) {
369       if (!IvarD->getSynthesize())
370         IndexCtx.handleReference(IvarD, D->getPropertyIvarDeclLoc(), nullptr,
371                                  D->getDeclContext(), SymbolRoleSet());
372     }
373
374     auto *ImplD = cast<ObjCImplDecl>(D->getDeclContext());
375     if (ObjCMethodDecl *MD = PD->getGetterMethodDecl()) {
376       if (MD->isPropertyAccessor() &&
377           !hasUserDefined(MD, ImplD))
378         IndexCtx.handleDecl(MD, D->getLocation(), SymbolRoleSet(), {}, ImplD);
379     }
380     if (ObjCMethodDecl *MD = PD->getSetterMethodDecl()) {
381       if (MD->isPropertyAccessor() &&
382           !hasUserDefined(MD, ImplD))
383         IndexCtx.handleDecl(MD, D->getLocation(), SymbolRoleSet(), {}, ImplD);
384     }
385     return true;
386   }
387
388   bool VisitNamespaceDecl(const NamespaceDecl *D) {
389     if (!IndexCtx.handleDecl(D))
390       return false;
391     IndexCtx.indexDeclContext(D);
392     return true;
393   }
394
395   bool VisitUsingDecl(const UsingDecl *D) {
396     const DeclContext *DC = D->getDeclContext()->getRedeclContext();
397     const NamedDecl *Parent = dyn_cast<NamedDecl>(DC);
398
399     IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent,
400                                          D->getLexicalDeclContext());
401     for (const auto *I : D->shadows())
402       IndexCtx.handleReference(I->getUnderlyingDecl(), D->getLocation(), Parent,
403                                D->getLexicalDeclContext(), SymbolRoleSet());
404     return true;
405   }
406
407   bool VisitUsingDirectiveDecl(const UsingDirectiveDecl *D) {
408     const DeclContext *DC = D->getDeclContext()->getRedeclContext();
409     const NamedDecl *Parent = dyn_cast<NamedDecl>(DC);
410
411     IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent,
412                                          D->getLexicalDeclContext());
413     return IndexCtx.handleReference(D->getNominatedNamespaceAsWritten(),
414                                     D->getLocation(), Parent,
415                                     D->getLexicalDeclContext(),
416                                     SymbolRoleSet());
417   }
418
419   bool VisitClassTemplateSpecializationDecl(const
420                                            ClassTemplateSpecializationDecl *D) {
421     // FIXME: Notify subsequent callbacks if info comes from implicit
422     // instantiation.
423     if (D->isThisDeclarationADefinition())
424       IndexCtx.indexTagDecl(D);
425     return true;
426   }
427
428   bool VisitTemplateDecl(const TemplateDecl *D) {
429     // FIXME: Template parameters.
430     return Visit(D->getTemplatedDecl());
431   }
432
433   bool VisitFriendDecl(const FriendDecl *D) {
434     if (auto ND = D->getFriendDecl()) {
435       // FIXME: Ignore a class template in a dependent context, these are not
436       // linked properly with their redeclarations, ending up with duplicate
437       // USRs.
438       // See comment "Friend templates are visible in fairly strange ways." in
439       // SemaTemplate.cpp which precedes code that prevents the friend template
440       // from becoming visible from the enclosing context.
441       if (isa<ClassTemplateDecl>(ND) && D->getDeclContext()->isDependentContext())
442         return true;
443       return Visit(ND);
444     }
445     if (auto Ty = D->getFriendType()) {
446       IndexCtx.indexTypeSourceInfo(Ty, cast<NamedDecl>(D->getDeclContext()));
447     }
448     return true;
449   }
450
451   bool VisitImportDecl(const ImportDecl *D) {
452     return IndexCtx.importedModule(D);
453   }
454 };
455
456 } // anonymous namespace
457
458 bool IndexingContext::indexDecl(const Decl *D) {
459   if (D->isImplicit() && shouldIgnoreIfImplicit(D))
460     return true;
461
462   if (isTemplateImplicitInstantiation(D))
463     return true;
464
465   IndexingDeclVisitor Visitor(*this);
466   bool ShouldContinue = Visitor.Visit(D);
467   if (!ShouldContinue)
468     return false;
469
470   if (!Visitor.Handled && isa<DeclContext>(D))
471     return indexDeclContext(cast<DeclContext>(D));
472
473   return true;
474 }
475
476 bool IndexingContext::indexDeclContext(const DeclContext *DC) {
477   for (const auto *I : DC->decls())
478     if (!indexDecl(I))
479       return false;
480   return true;
481 }
482
483 bool IndexingContext::indexTopLevelDecl(const Decl *D) {
484   if (D->getLocation().isInvalid())
485     return true;
486
487   if (isa<ObjCMethodDecl>(D))
488     return true; // Wait for the objc container.
489
490   return indexDecl(D);
491 }
492
493 bool IndexingContext::indexDeclGroupRef(DeclGroupRef DG) {
494   for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I)
495     if (!indexTopLevelDecl(*I))
496       return false;
497   return true;
498 }