clang  3.9.0
IndexBody.cpp
Go to the documentation of this file.
1 //===- IndexBody.cpp - Indexing statements --------------------------------===//
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 
13 using namespace clang;
14 using namespace clang::index;
15 
16 namespace {
17 
18 class BodyIndexer : public RecursiveASTVisitor<BodyIndexer> {
19  IndexingContext &IndexCtx;
20  const NamedDecl *Parent;
21  const DeclContext *ParentDC;
22  SmallVector<Stmt*, 16> StmtStack;
23 
25 public:
26  BodyIndexer(IndexingContext &indexCtx,
27  const NamedDecl *Parent, const DeclContext *DC)
28  : IndexCtx(indexCtx), Parent(Parent), ParentDC(DC) { }
29 
30  bool shouldWalkTypesOfTypeLocs() const { return false; }
31 
32  bool dataTraverseStmtPre(Stmt *S) {
33  StmtStack.push_back(S);
34  return true;
35  }
36 
37  bool dataTraverseStmtPost(Stmt *S) {
38  assert(StmtStack.back() == S);
39  StmtStack.pop_back();
40  return true;
41  }
42 
43  bool TraverseTypeLoc(TypeLoc TL) {
44  IndexCtx.indexTypeLoc(TL, Parent, ParentDC);
45  return true;
46  }
47 
48  bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) {
49  IndexCtx.indexNestedNameSpecifierLoc(NNS, Parent, ParentDC);
50  return true;
51  }
52 
53  SymbolRoleSet getRolesForRef(const Expr *E,
55  SymbolRoleSet Roles{};
56  assert(!StmtStack.empty() && E == StmtStack.back());
57  if (StmtStack.size() == 1)
58  return Roles;
59  auto It = StmtStack.end()-2;
60  while (isa<CastExpr>(*It) || isa<ParenExpr>(*It)) {
61  if (auto ICE = dyn_cast<ImplicitCastExpr>(*It)) {
62  if (ICE->getCastKind() == CK_LValueToRValue)
63  Roles |= (unsigned)(unsigned)SymbolRole::Read;
64  }
65  if (It == StmtStack.begin())
66  break;
67  --It;
68  }
69  const Stmt *Parent = *It;
70 
71  if (auto BO = dyn_cast<BinaryOperator>(Parent)) {
72  if (BO->getOpcode() == BO_Assign && BO->getLHS()->IgnoreParenCasts() == E)
73  Roles |= (unsigned)SymbolRole::Write;
74 
75  } else if (auto UO = dyn_cast<UnaryOperator>(Parent)) {
76  if (UO->isIncrementDecrementOp()) {
77  Roles |= (unsigned)SymbolRole::Read;
78  Roles |= (unsigned)SymbolRole::Write;
79  } else if (UO->getOpcode() == UO_AddrOf) {
81  }
82 
83  } else if (auto CA = dyn_cast<CompoundAssignOperator>(Parent)) {
84  if (CA->getLHS()->IgnoreParenCasts() == E) {
85  Roles |= (unsigned)SymbolRole::Read;
86  Roles |= (unsigned)SymbolRole::Write;
87  }
88 
89  } else if (auto CE = dyn_cast<CallExpr>(Parent)) {
90  if (CE->getCallee()->IgnoreParenCasts() == E) {
91  addCallRole(Roles, Relations);
92  if (auto *ME = dyn_cast<MemberExpr>(E)) {
93  if (auto *CXXMD = dyn_cast_or_null<CXXMethodDecl>(ME->getMemberDecl()))
94  if (CXXMD->isVirtual() && !ME->hasQualifier()) {
95  Roles |= (unsigned)SymbolRole::Dynamic;
96  auto BaseTy = ME->getBase()->IgnoreImpCasts()->getType();
97  if (!BaseTy.isNull())
98  if (auto *CXXRD = BaseTy->getPointeeCXXRecordDecl())
99  Relations.emplace_back((unsigned)SymbolRole::RelationReceivedBy,
100  CXXRD);
101  }
102  }
103  } else if (auto CXXOp = dyn_cast<CXXOperatorCallExpr>(CE)) {
104  if (CXXOp->getNumArgs() > 0 && CXXOp->getArg(0)->IgnoreParenCasts() == E) {
105  OverloadedOperatorKind Op = CXXOp->getOperator();
106  if (Op == OO_Equal) {
107  Roles |= (unsigned)SymbolRole::Write;
108  } else if ((Op >= OO_PlusEqual && Op <= OO_PipeEqual) ||
109  Op == OO_LessLessEqual || Op == OO_GreaterGreaterEqual ||
110  Op == OO_PlusPlus || Op == OO_MinusMinus) {
111  Roles |= (unsigned)SymbolRole::Read;
112  Roles |= (unsigned)SymbolRole::Write;
113  } else if (Op == OO_Amp) {
115  }
116  }
117  }
118  }
119 
120  return Roles;
121  }
122 
123  void addCallRole(SymbolRoleSet &Roles,
124  SmallVectorImpl<SymbolRelation> &Relations) {
125  Roles |= (unsigned)SymbolRole::Call;
126  if (auto *FD = dyn_cast<FunctionDecl>(ParentDC))
127  Relations.emplace_back((unsigned)SymbolRole::RelationCalledBy, FD);
128  else if (auto *MD = dyn_cast<ObjCMethodDecl>(ParentDC))
129  Relations.emplace_back((unsigned)SymbolRole::RelationCalledBy, MD);
130  }
131 
132  bool VisitDeclRefExpr(DeclRefExpr *E) {
134  SymbolRoleSet Roles = getRolesForRef(E, Relations);
135  return IndexCtx.handleReference(E->getDecl(), E->getLocation(),
136  Parent, ParentDC, Roles, Relations, E);
137  }
138 
139  bool VisitMemberExpr(MemberExpr *E) {
140  SourceLocation Loc = E->getMemberLoc();
141  if (Loc.isInvalid())
142  Loc = E->getLocStart();
144  SymbolRoleSet Roles = getRolesForRef(E, Relations);
145  return IndexCtx.handleReference(E->getMemberDecl(), Loc,
146  Parent, ParentDC, Roles, Relations, E);
147  }
148 
149  bool VisitDesignatedInitExpr(DesignatedInitExpr *E) {
150  for (DesignatedInitExpr::Designator &D : llvm::reverse(E->designators())) {
151  if (D.isFieldDesignator())
152  return IndexCtx.handleReference(D.getField(), D.getFieldLoc(), Parent,
153  ParentDC, SymbolRoleSet(), {}, E);
154  }
155  return true;
156  }
157 
158  bool VisitObjCIvarRefExpr(ObjCIvarRefExpr *E) {
160  SymbolRoleSet Roles = getRolesForRef(E, Relations);
161  return IndexCtx.handleReference(E->getDecl(), E->getLocation(),
162  Parent, ParentDC, Roles, Relations, E);
163  }
164 
165  bool VisitObjCMessageExpr(ObjCMessageExpr *E) {
166  auto isDynamic = [](const ObjCMessageExpr *MsgE)->bool {
167  if (MsgE->getReceiverKind() != ObjCMessageExpr::Instance)
168  return false;
169  if (auto *RecE = dyn_cast<ObjCMessageExpr>(
170  MsgE->getInstanceReceiver()->IgnoreParenCasts())) {
171  if (RecE->getMethodFamily() == OMF_alloc)
172  return false;
173  }
174  return true;
175  };
176 
177  if (ObjCMethodDecl *MD = E->getMethodDecl()) {
178  SymbolRoleSet Roles{};
180  addCallRole(Roles, Relations);
181  if (E->isImplicit())
182  Roles |= (unsigned)SymbolRole::Implicit;
183 
184  if (isDynamic(E)) {
185  Roles |= (unsigned)SymbolRole::Dynamic;
186  if (auto *RecD = E->getReceiverInterface())
187  Relations.emplace_back((unsigned)SymbolRole::RelationReceivedBy, RecD);
188  }
189 
190  return IndexCtx.handleReference(MD, E->getSelectorStartLoc(),
191  Parent, ParentDC, Roles, Relations, E);
192  }
193  return true;
194  }
195 
196  bool VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E) {
197  if (E->isExplicitProperty())
198  return IndexCtx.handleReference(E->getExplicitProperty(), E->getLocation(),
199  Parent, ParentDC, SymbolRoleSet(), {}, E);
200 
201  // No need to do a handleReference for the objc method, because there will
202  // be a message expr as part of PseudoObjectExpr.
203  return true;
204  }
205 
206  bool VisitMSPropertyRefExpr(MSPropertyRefExpr *E) {
207  return IndexCtx.handleReference(E->getPropertyDecl(), E->getMemberLoc(),
208  Parent, ParentDC, SymbolRoleSet(), {}, E);
209  }
210 
211  bool VisitObjCProtocolExpr(ObjCProtocolExpr *E) {
212  return IndexCtx.handleReference(E->getProtocol(), E->getProtocolIdLoc(),
213  Parent, ParentDC, SymbolRoleSet(), {}, E);
214  }
215 
216  bool passObjCLiteralMethodCall(const ObjCMethodDecl *MD, const Expr *E) {
217  SymbolRoleSet Roles{};
219  addCallRole(Roles, Relations);
220  Roles |= (unsigned)SymbolRole::Implicit;
221  return IndexCtx.handleReference(MD, E->getLocStart(),
222  Parent, ParentDC, Roles, Relations, E);
223  }
224 
225  bool VisitObjCBoxedExpr(ObjCBoxedExpr *E) {
226  if (ObjCMethodDecl *MD = E->getBoxingMethod()) {
227  return passObjCLiteralMethodCall(MD, E);
228  }
229  return true;
230  }
231 
232  bool VisitObjCDictionaryLiteral(ObjCDictionaryLiteral *E) {
233  if (ObjCMethodDecl *MD = E->getDictWithObjectsMethod()) {
234  return passObjCLiteralMethodCall(MD, E);
235  }
236  return true;
237  }
238 
239  bool VisitObjCArrayLiteral(ObjCArrayLiteral *E) {
240  if (ObjCMethodDecl *MD = E->getArrayWithObjectsMethod()) {
241  return passObjCLiteralMethodCall(MD, E);
242  }
243  return true;
244  }
245 
246  bool VisitCXXConstructExpr(CXXConstructExpr *E) {
247  SymbolRoleSet Roles{};
249  addCallRole(Roles, Relations);
250  return IndexCtx.handleReference(E->getConstructor(), E->getLocation(),
251  Parent, ParentDC, Roles, Relations, E);
252  }
253 
254  bool TraverseCXXOperatorCallExpr(CXXOperatorCallExpr *E,
255  DataRecursionQueue *Q = nullptr) {
256  if (E->getOperatorLoc().isInvalid())
257  return true; // implicit.
258  return base::TraverseCXXOperatorCallExpr(E, Q);
259  }
260 
261  bool VisitDeclStmt(DeclStmt *S) {
262  if (IndexCtx.shouldIndexFunctionLocalSymbols()) {
263  IndexCtx.indexDeclGroupRef(S->getDeclGroup());
264  return true;
265  }
266 
267  DeclGroupRef DG = S->getDeclGroup();
268  for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I) {
269  const Decl *D = *I;
270  if (!D)
271  continue;
272  if (!IndexCtx.isFunctionLocalDecl(D))
273  IndexCtx.indexTopLevelDecl(D);
274  }
275 
276  return true;
277  }
278 
279  bool TraverseLambdaCapture(LambdaExpr *LE, const LambdaCapture *C) {
280  if (C->capturesThis() || C->capturesVLAType())
281  return true;
282 
283  if (C->capturesVariable() && IndexCtx.shouldIndexFunctionLocalSymbols())
284  return IndexCtx.handleReference(C->getCapturedVar(), C->getLocation(),
285  Parent, ParentDC, SymbolRoleSet());
286 
287  // FIXME: Lambda init-captures.
288  return true;
289  }
290 
291  // RecursiveASTVisitor visits both syntactic and semantic forms, duplicating
292  // the things that we visit. Make sure to only visit the semantic form.
293  // Also visit things that are in the syntactic form but not the semantic one,
294  // for example the indices in DesignatedInitExprs.
295  bool TraverseInitListExpr(InitListExpr *S, DataRecursionQueue *Q = nullptr) {
296 
297  class SyntacticFormIndexer :
298  public RecursiveASTVisitor<SyntacticFormIndexer> {
299  IndexingContext &IndexCtx;
300  const NamedDecl *Parent;
301  const DeclContext *ParentDC;
302 
303  public:
304  SyntacticFormIndexer(IndexingContext &indexCtx,
305  const NamedDecl *Parent, const DeclContext *DC)
306  : IndexCtx(indexCtx), Parent(Parent), ParentDC(DC) { }
307 
308  bool shouldWalkTypesOfTypeLocs() const { return false; }
309 
310  bool VisitDesignatedInitExpr(DesignatedInitExpr *E) {
311  for (DesignatedInitExpr::Designator &D : llvm::reverse(E->designators())) {
312  if (D.isFieldDesignator())
313  return IndexCtx.handleReference(D.getField(), D.getFieldLoc(),
314  Parent, ParentDC, SymbolRoleSet(),
315  {}, E);
316  }
317  return true;
318  }
319  };
320 
321  auto visitForm = [&](InitListExpr *Form) {
322  for (Stmt *SubStmt : Form->children()) {
323  if (!TraverseStmt(SubStmt, Q))
324  return false;
325  }
326  return true;
327  };
328 
329  InitListExpr *SemaForm = S->isSemanticForm() ? S : S->getSemanticForm();
330  InitListExpr *SyntaxForm = S->isSemanticForm() ? S->getSyntacticForm() : S;
331 
332  if (SemaForm) {
333  // Visit things present in syntactic form but not the semantic form.
334  if (SyntaxForm) {
335  SyntacticFormIndexer(IndexCtx, Parent, ParentDC).TraverseStmt(SyntaxForm);
336  }
337  return visitForm(SemaForm);
338  }
339 
340  // No semantic, try the syntactic.
341  if (SyntaxForm) {
342  return visitForm(SyntaxForm);
343  }
344 
345  return true;
346  }
347 };
348 
349 } // anonymous namespace
350 
351 void IndexingContext::indexBody(const Stmt *S, const NamedDecl *Parent,
352  const DeclContext *DC) {
353  if (!S)
354  return;
355 
356  if (!DC)
357  DC = Parent->getLexicalDeclContext();
358  BodyIndexer(*this, Parent, DC).TraverseStmt(const_cast<Stmt*>(S));
359 }
ObjCPropertyRefExpr - A dot-syntax expression to access an ObjC property.
Definition: ExprObjC.h:539
A call to an overloaded operator written using operator syntax.
Definition: ExprCXX.h:52
Represents a single C99 designator.
Definition: Expr.h:4028
ValueDecl * getMemberDecl() const
Retrieve the member declaration to which this expression refers.
Definition: Expr.h:2411
The receiver is an object instance.
Definition: ExprObjC.h:1005
const DeclGroupRef getDeclGroup() const
Definition: Stmt.h:464
SourceLocation getLocation() const
Definition: ExprObjC.h:518
iterator end()
Definition: DeclGroup.h:108
SourceLocation getProtocolIdLoc() const
Definition: ExprObjC.h:456
InitListExpr * getSyntacticForm() const
Definition: Expr.h:3882
Represents a call to a C++ constructor.
Definition: ExprCXX.h:1162
Describes the capture of a variable or of this, or of a C++1y init-capture.
Definition: LambdaCapture.h:26
bool isExplicitProperty() const
Definition: ExprObjC.h:631
ObjCMethodDecl - Represents an instance or class method declaration.
Definition: DeclObjC.h:113
virtual bool isDynamic(OpenMPScheduleClauseKind ScheduleKind) const
Check if the specified ScheduleKind is dynamic.
SourceLocation getOperatorLoc() const
Returns the location of the operator symbol in the expression.
Definition: ExprCXX.h:84
SourceLocation getLocation() const
Definition: Expr.h:1025
Base wrapper for a particular "section" of type source info.
Definition: TypeLoc.h:40
Represents a C99 designated initializer expression.
Definition: Expr.h:3953
ObjCProtocolDecl * getProtocol() const
Definition: ExprObjC.h:453
A C++ nested-name-specifier augmented with source location information.
bool isSemanticForm() const
Definition: Expr.h:3878
ObjCArrayLiteral - used for objective-c array containers; as in: @["Hello", NSApp, [NSNumber numberWithInt:42]];.
Definition: ExprObjC.h:144
Describes an C or C++ initializer list.
Definition: Expr.h:3746
ObjCMethodDecl * getBoxingMethod() const
Definition: ExprObjC.h:111
iterator begin()
Definition: DeclGroup.h:102
VarDecl * getCapturedVar() const
Retrieve the declaration of the local variable being captured.
bool capturesVLAType() const
Determine whether this captures a variable length array bound expression.
Definition: LambdaCapture.h:95
A C++ lambda expression, which produces a function object (of unspecified type) that can be invoked l...
Definition: ExprCXX.h:1503
A class that does preordor or postorder depth-first traversal on the entire Clang AST and visits each...
detail::InMemoryDirectory::const_iterator I
bool isInvalid() const
MSPropertyDecl * getPropertyDecl() const
Definition: ExprCXX.h:709
ObjCIvarDecl * getDecl()
Definition: ExprObjC.h:505
unsigned SymbolRoleSet
Definition: IndexSymbol.h:93
InitListExpr * getSemanticForm() const
Definition: Expr.h:3879
SourceLocation getMemberLoc() const
Definition: ExprCXX.h:711
const ObjCMethodDecl * getMethodDecl() const
Definition: ExprObjC.h:1251
llvm::MutableArrayRef< Designator > designators()
Definition: Expr.h:4156
Expr - This represents one expression.
Definition: Expr.h:105
SourceLocation getLocation() const
Definition: ExprCXX.h:1227
ObjCDictionaryLiteral - AST node to represent objective-c dictionary literals; as in:"name" : NSUserN...
Definition: ExprObjC.h:257
ObjCInterfaceDecl * getReceiverInterface() const
Retrieve the Objective-C interface to which this message is being directed, if known.
Definition: ExprObjC.cpp:327
SourceLocation getLocation() const
Retrieve the source location of the capture.
SourceLocation getLocation() const
Definition: ExprObjC.h:689
An expression that sends a message to the given Objective-C object or class.
Definition: ExprObjC.h:860
A member reference to an MSPropertyDecl.
Definition: ExprCXX.h:663
ValueDecl * getDecl()
Definition: Expr.h:1017
Encodes a location in the source.
DeclStmt - Adaptor class for mixing declarations with statements and expressions. ...
Definition: Stmt.h:443
ObjCProtocolExpr used for protocol expression in Objective-C.
Definition: ExprObjC.h:441
SourceLocation getSelectorStartLoc() const
Definition: ExprObjC.h:1313
ObjCBoxedExpr - used for generalized expression boxing.
Definition: ExprObjC.h:94
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
Definition: DeclBase.h:1135
OverloadedOperatorKind
Enumeration specifying the different kinds of C++ overloaded operators.
Definition: OperatorKinds.h:22
ObjCMethodDecl * getArrayWithObjectsMethod() const
Definition: ExprObjC.h:196
detail::InMemoryDirectory::const_iterator E
ObjCMethodDecl * getDictWithObjectsMethod() const
Definition: ExprObjC.h:323
SourceLocation getMemberLoc() const
getMemberLoc - Return the location of the "member", in X->F, it is the location of 'F'...
Definition: Expr.h:2515
CXXConstructorDecl * getConstructor() const
Get the constructor that this expression will (ultimately) call.
Definition: ExprCXX.h:1225
ObjCPropertyDecl * getExplicitProperty() const
Definition: ExprObjC.h:633
ObjCIvarRefExpr - A reference to an ObjC instance variable.
Definition: ExprObjC.h:479
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
Definition: Expr.h:2315
bool isImplicit() const
Indicates whether the message send was implicitly generated by the implementation.
Definition: ExprObjC.h:1132
A reference to a declared variable, function, enum, etc.
Definition: Expr.h:932
bool capturesThis() const
Determine whether this capture handles the C++ this pointer.
Definition: LambdaCapture.h:83
void indexBody(const Stmt *S, const NamedDecl *Parent, const DeclContext *DC=nullptr)
Definition: IndexBody.cpp:351
NamedDecl - This represents a decl with a name.
Definition: Decl.h:213
bool capturesVariable() const
Determine whether this capture handles a variable.
Definition: LambdaCapture.h:89
SourceLocation getLocStart() const LLVM_READONLY
Definition: Expr.cpp:1462