]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/clang/lib/Index/IndexBody.cpp
Merge ^/head r305346 through r305360.
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / clang / lib / Index / IndexBody.cpp
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"
11 #include "clang/AST/RecursiveASTVisitor.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
24   typedef RecursiveASTVisitor<BodyIndexer> base;
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,
54                                SmallVectorImpl<SymbolRelation> &Relations) {
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) {
80         Roles |= (unsigned)SymbolRole::AddressOf;
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) {
114             Roles |= (unsigned)SymbolRole::AddressOf;
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) {
133     SmallVector<SymbolRelation, 4> Relations;
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();
143     SmallVector<SymbolRelation, 4> Relations;
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) {
159     SmallVector<SymbolRelation, 4> Relations;
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{};
179       SmallVector<SymbolRelation, 2> Relations;
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{};
218     SmallVector<SymbolRelation, 2> Relations;
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{};
248     SmallVector<SymbolRelation, 2> Relations;
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 }