clang  3.9.0
IndexingContext.cpp
Go to the documentation of this file.
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"
12 #include "clang/AST/ASTContext.h"
13 #include "clang/AST/DeclTemplate.h"
14 #include "clang/AST/DeclObjC.h"
16 
17 using namespace clang;
18 using namespace index;
19 
21  return IndexOpts.IndexFunctionLocals;
22 }
23 
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 
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 
44  const NamedDecl *Parent,
45  const DeclContext *DC,
46  SymbolRoleSet Roles,
47  ArrayRef<SymbolRelation> Relations,
48  const Expr *RefE,
49  const Decl *RefD) {
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 
61  SourceLocation Loc;
62  auto IdLocs = ImportD->getIdentifierLocs();
63  if (!IdLocs.empty())
64  Loc = IdLocs.front();
65  else
66  Loc = ImportD->getLocation();
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) {
86  return true;
89  break;
90  }
91  }
92 
94  if (ImportD->isImplicit())
95  Roles |= (unsigned)SymbolRole::Implicit;
96 
97  return DataConsumer.handleModuleOccurence(ImportD, Roles, FID, Offset);
98 }
99 
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;
119  llvm_unreachable("Not a sema linkage");
120  case ExternalLinkage:
121  return false;
122  }
123  }
124 
125  return true;
126 }
127 
131  SD = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
132  TKind = SD->getSpecializationKind();
133  }
134  if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
135  TKind = FD->getTemplateSpecializationKind();
136  }
137  switch (TKind) {
138  case TSK_Undeclared:
140  return false;
144  return true;
145  }
146  llvm_unreachable("invalid TemplateSpecializationKind");
147 }
148 
149 bool IndexingContext::shouldIgnoreIfImplicit(const Decl *D) {
150  if (isa<ObjCInterfaceDecl>(D))
151  return false;
152  if (isa<ObjCCategoryDecl>(D))
153  return false;
154  if (isa<ObjCIvarDecl>(D))
155  return false;
156  if (isa<ObjCMethodDecl>(D))
157  return false;
158  if (isa<ImportDecl>(D))
159  return false;
160  return true;
161 }
162 
165  SD = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
166  return SD->getTemplateInstantiationPattern();
167  }
168  if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
169  return FD->getTemplateInstantiationPattern();
170  }
171  return nullptr;
172 }
173 
174 static bool isDeclADefinition(const Decl *D, const DeclContext *ContainerDC, ASTContext &Ctx) {
175  if (auto VD = dyn_cast<VarDecl>(D))
176  return VD->isThisDeclarationADefinition(Ctx);
177 
178  if (auto FD = dyn_cast<FunctionDecl>(D))
179  return FD->isThisDeclarationADefinition();
180 
181  if (auto TD = dyn_cast<TagDecl>(D))
182  return TD->isThisDeclarationADefinition();
183 
184  if (auto MD = dyn_cast<ObjCMethodDecl>(D))
185  return MD->isThisDeclarationADefinition() || isa<ObjCImplDecl>(ContainerDC);
186 
187  if (isa<TypedefNameDecl>(D) ||
188  isa<EnumConstantDecl>(D) ||
189  isa<FieldDecl>(D) ||
190  isa<MSPropertyDecl>(D) ||
191  isa<ObjCImplDecl>(D) ||
192  isa<ObjCPropertyImplDecl>(D))
193  return true;
194 
195  return false;
196 }
197 
198 static const Decl *adjustParent(const Decl *Parent) {
199  if (!Parent)
200  return nullptr;
201  for (;; Parent = cast<Decl>(Parent->getDeclContext())) {
202  if (isa<TranslationUnitDecl>(Parent))
203  return nullptr;
204  if (isa<LinkageSpecDecl>(Parent) || isa<BlockDecl>(Parent))
205  continue;
206  if (auto NS = dyn_cast<NamespaceDecl>(Parent)) {
207  if (NS->isAnonymousNamespace())
208  continue;
209  } else if (auto RD = dyn_cast<RecordDecl>(Parent)) {
210  if (RD->isAnonymousStructOrUnion())
211  continue;
212  } else if (auto FD = dyn_cast<FieldDecl>(Parent)) {
213  if (FD->getDeclName().isEmpty())
214  continue;
215  }
216  return Parent;
217  }
218 }
219 
220 static const Decl *getCanonicalDecl(const Decl *D) {
221  D = D->getCanonicalDecl();
222  if (auto TD = dyn_cast<TemplateDecl>(D)) {
223  D = TD->getTemplatedDecl();
224  assert(D->isCanonicalDecl());
225  }
226 
227  return D;
228 }
229 
230 bool IndexingContext::handleDeclOccurrence(const Decl *D, SourceLocation Loc,
231  bool IsRef, const Decl *Parent,
232  SymbolRoleSet Roles,
233  ArrayRef<SymbolRelation> Relations,
234  const Expr *OrigE,
235  const Decl *OrigD,
236  const DeclContext *ContainerDC) {
237  if (D->isImplicit() && !isa<ObjCMethodDecl>(D))
238  return true;
239  if (!isa<NamedDecl>(D) ||
240  (cast<NamedDecl>(D)->getDeclName().isEmpty() &&
241  !isa<TagDecl>(D) && !isa<ObjCCategoryDecl>(D)))
242  return true;
243 
245  Loc = SM.getFileLoc(Loc);
246  if (Loc.isInvalid())
247  return true;
248 
249  FileID FID;
250  unsigned Offset;
251  std::tie(FID, Offset) = SM.getDecomposedLoc(Loc);
252  if (FID.isInvalid())
253  return true;
254 
255  bool Invalid = false;
256  const SrcMgr::SLocEntry &SEntry = SM.getSLocEntry(FID, &Invalid);
257  if (Invalid || !SEntry.isFile())
258  return true;
259 
260  if (SEntry.getFile().getFileCharacteristic() != SrcMgr::C_User) {
261  switch (IndexOpts.SystemSymbolFilter) {
263  return true;
265  if (IsRef)
266  return true;
267  break;
269  break;
270  }
271  }
272 
274  if (!IsRef)
275  return true;
277  if (!D)
278  return true;
280  }
281 
282  if (!OrigD)
283  OrigD = D;
284 
285  if (IsRef)
287  else if (isDeclADefinition(D, ContainerDC, *Ctx))
288  Roles |= (unsigned)SymbolRole::Definition;
289  else
291 
292  D = getCanonicalDecl(D);
293  if (D->isImplicit() && !isa<ObjCMethodDecl>(D) &&
294  !(isa<FunctionDecl>(D) && cast<FunctionDecl>(D)->getBuiltinID())) {
295  // operator new declarations will link to the implicit one as canonical.
296  return true;
297  }
298  Parent = adjustParent(Parent);
299  if (Parent)
300  Parent = getCanonicalDecl(Parent);
301  assert((!Parent || !Parent->isImplicit() ||
302  (isa<FunctionDecl>(Parent) &&
303  cast<FunctionDecl>(Parent)->getBuiltinID()) ||
304  isa<ObjCInterfaceDecl>(Parent) || isa<ObjCMethodDecl>(Parent)) &&
305  "unexpected implicit parent!");
306 
307  SmallVector<SymbolRelation, 6> FinalRelations;
308  FinalRelations.reserve(Relations.size()+1);
309 
310  auto addRelation = [&](SymbolRelation Rel) {
311  auto It = std::find_if(FinalRelations.begin(), FinalRelations.end(),
312  [&](SymbolRelation Elem)->bool {
313  return Elem.RelatedSymbol == Rel.RelatedSymbol;
314  });
315  if (It != FinalRelations.end()) {
316  It->Roles |= Rel.Roles;
317  } else {
318  FinalRelations.push_back(Rel);
319  }
320  Roles |= Rel.Roles;
321  };
322 
323  if (!IsRef && Parent && !cast<DeclContext>(Parent)->isFunctionOrMethod()) {
324  addRelation(SymbolRelation{(unsigned)SymbolRole::RelationChildOf, Parent});
325  }
326  for (auto &Rel : Relations) {
327  addRelation(SymbolRelation(Rel.Roles,
328  Rel.RelatedSymbol->getCanonicalDecl()));
329  }
330 
331  IndexDataConsumer::ASTNodeInfo Node{ OrigE, OrigD, Parent, ContainerDC };
332  return DataConsumer.handleDeclOccurence(D, Roles, FinalRelations, FID, Offset,
333  Node);
334 }
Defines the clang::ASTContext interface.
static const Decl * getCanonicalDecl(const Decl *D)
FunctionDecl - An instance of this class is created to represent a function declaration or definition...
Definition: Decl.h:1561
External linkage, which indicates that the entity can be referred to from other translation units...
Definition: Linkage.h:50
This is a discriminated union of FileInfo and ExpansionInfo.
Represents a relation to another symbol for a symbol occurrence.
Definition: IndexSymbol.h:96
No linkage, which means that the entity is unique and can only be referred to from within its scope...
Definition: Linkage.h:28
Defines the SourceManager interface.
virtual bool handleDeclOccurence(const Decl *D, SymbolRoleSet Roles, ArrayRef< SymbolRelation > Relations, FileID FID, unsigned Offset, ASTNodeInfo ASTNode)
const SrcMgr::SLocEntry & getSLocEntry(FileID FID, bool *Invalid=nullptr) const
Defines the C++ template declaration subclasses.
bool handleReference(const NamedDecl *D, SourceLocation Loc, const NamedDecl *Parent, const DeclContext *DC, SymbolRoleSet Roles, ArrayRef< SymbolRelation > Relations=None, const Expr *RefE=nullptr, const Decl *RefD=nullptr)
CharacteristicKind getFileCharacteristic() const
Return whether this is a system header or not.
Represents a class template specialization, which refers to a class template with a given set of temp...
static const Decl * adjustTemplateImplicitInstantiation(const Decl *D)
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:92
uint32_t Offset
Definition: CacheTokens.cpp:44
SourceLocation getFileLoc(SourceLocation Loc) const
Given Loc, if it is a macro location return the expansion location or the spelling location...
bool isInvalid() const
ArrayRef< SourceLocation > getIdentifierLocs() const
Retrieves the locations of each of the identifiers that make up the complete module name in the impor...
Definition: Decl.cpp:4269
Expr - This represents one expression.
Definition: Expr.h:105
virtual bool handleModuleOccurence(const ImportDecl *ImportD, SymbolRoleSet Roles, FileID FID, unsigned Offset)
static bool isTemplateImplicitInstantiation(const Decl *D)
This template specialization was implicitly instantiated from a template.
Definition: Specifiers.h:147
const SourceManager & SM
Definition: Format.cpp:1184
SystemSymbolFilterKind SystemSymbolFilter
static bool isFunctionLocalDecl(const Decl *D)
Encodes a location in the source.
static const Decl * adjustParent(const Decl *Parent)
const FileInfo & getFile() const
This template specialization was instantiated from a template due to an explicit instantiation defini...
Definition: Specifiers.h:159
This template specialization was formed from a template-id but has not yet been declared, defined, or instantiated.
Definition: Specifiers.h:144
Describes a module import declaration, which makes the contents of the named module visible in the cu...
Definition: Decl.h:3728
static bool isDeclADefinition(const Decl *D, const DeclContext *ContainerDC, ASTContext &Ctx)
ast_type_traits::DynTypedNode Node
An opaque identifier used by SourceManager which refers to a source file (MemoryBuffer) along with it...
External linkage within a unique namespace.
Definition: Linkage.h:42
bool handleDecl(const Decl *D, SymbolRoleSet Roles=SymbolRoleSet(), ArrayRef< SymbolRelation > Relations=None)
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
Definition: DeclBase.h:1135
This template specialization was instantiated from a template due to an explicit instantiation declar...
Definition: Specifiers.h:155
TemplateSpecializationKind
Describes the kind of template specialization that a particular template specialization declaration r...
Definition: Specifiers.h:141
This template specialization was declared or defined by an explicit specialization (C++ [temp...
Definition: Specifiers.h:151
static bool isFunctionOrMethod(const Decl *D)
isFunctionOrMethod - Return true if the given decl has function type (function or function-typed vari...
bool isInvalid() const
bool importedModule(const ImportDecl *ImportD)
bool shouldIndexFunctionLocalSymbols() const
Internal linkage, which indicates that the entity can be referred to from within the translation unit...
Definition: Linkage.h:33
SourceManager & getSourceManager()
Definition: ASTContext.h:561
No linkage according to the standard, but is visible from other translation units because of types de...
Definition: Linkage.h:46
NamedDecl - This represents a decl with a name.
Definition: Decl.h:213
std::pair< FileID, unsigned > getDecomposedLoc(SourceLocation Loc) const
Decompose the specified location into a raw FileID + Offset pair.
This class handles loading and caching of source files into memory.