@@ -188,90 +188,96 @@ static MemberExpr *getMemberForAccessor(const CXXMemberCallExpr &C) {
188
188
return nullptr ;
189
189
}
190
190
191
- static void getReferencedDecls (const Decl &D, ReferencedDecls &Referenced) {
192
- insertIfGlobal (D, Referenced.Globals );
193
- insertIfFunction (D, Referenced.Functions );
194
- if (const auto *Decomp = dyn_cast<DecompositionDecl>(&D))
195
- for (const auto *B : Decomp->bindings ())
196
- if (auto *ME = dyn_cast_or_null<MemberExpr>(B->getBinding ()))
197
- // FIXME: should we be using `E->getFoundDecl()`?
198
- if (const auto *FD = dyn_cast<FieldDecl>(ME->getMemberDecl ()))
199
- Referenced.Fields .insert (FD);
200
- }
191
+ class ReferencedDeclsVisitor
192
+ : public AnalysisASTVisitor<ReferencedDeclsVisitor> {
193
+ public:
194
+ ReferencedDeclsVisitor (ReferencedDecls &Referenced)
195
+ : Referenced(Referenced) {}
196
+
197
+ void TraverseConstructorInits (const CXXConstructorDecl *Ctor) {
198
+ for (const CXXCtorInitializer *Init : Ctor->inits ()) {
199
+ if (Init->isMemberInitializer ()) {
200
+ Referenced.Fields .insert (Init->getMember ());
201
+ } else if (Init->isIndirectMemberInitializer ()) {
202
+ for (const auto *I : Init->getIndirectMember ()->chain ())
203
+ Referenced.Fields .insert (cast<FieldDecl>(I));
204
+ }
205
+
206
+ Expr *InitExpr = Init->getInit ();
207
+
208
+ // Also collect declarations referenced in `InitExpr`.
209
+ TraverseStmt (InitExpr);
201
210
202
- // / Traverses `S` and inserts into `Referenced` any declarations that are
203
- // / declared in or referenced from sub-statements.
204
- static void getReferencedDecls (const Stmt &S, ReferencedDecls &Referenced) {
205
- for (auto *Child : S.children ())
206
- if (Child != nullptr )
207
- getReferencedDecls (*Child, Referenced);
208
- if (const auto *DefaultArg = dyn_cast<CXXDefaultArgExpr>(&S))
209
- getReferencedDecls (*DefaultArg->getExpr (), Referenced);
210
- if (const auto *DefaultInit = dyn_cast<CXXDefaultInitExpr>(&S))
211
- getReferencedDecls (*DefaultInit->getExpr (), Referenced);
212
-
213
- if (auto *DS = dyn_cast<DeclStmt>(&S)) {
214
- if (DS->isSingleDecl ())
215
- getReferencedDecls (*DS->getSingleDecl (), Referenced);
216
- else
217
- for (auto *D : DS->getDeclGroup ())
218
- getReferencedDecls (*D, Referenced);
219
- } else if (auto *E = dyn_cast<DeclRefExpr>(&S)) {
211
+ // If this is a `CXXDefaultInitExpr`, also collect declarations referenced
212
+ // within the default expression.
213
+ if (auto *DefaultInit = dyn_cast<CXXDefaultInitExpr>(InitExpr))
214
+ TraverseStmt (DefaultInit->getExpr ());
215
+ }
216
+ }
217
+
218
+ bool VisitDecl (Decl *D) {
219
+ insertIfGlobal (*D, Referenced.Globals );
220
+ insertIfFunction (*D, Referenced.Functions );
221
+ return true ;
222
+ }
223
+
224
+ bool VisitDeclRefExpr (DeclRefExpr *E) {
220
225
insertIfGlobal (*E->getDecl (), Referenced.Globals );
221
226
insertIfFunction (*E->getDecl (), Referenced.Functions );
222
- } else if (const auto *C = dyn_cast<CXXMemberCallExpr>(&S)) {
227
+ return true ;
228
+ }
229
+
230
+ bool VisitCXXMemberCallExpr (CXXMemberCallExpr *C) {
223
231
// If this is a method that returns a member variable but does nothing else,
224
232
// model the field of the return value.
225
233
if (MemberExpr *E = getMemberForAccessor (*C))
226
234
if (const auto *FD = dyn_cast<FieldDecl>(E->getMemberDecl ()))
227
235
Referenced.Fields .insert (FD);
228
- } else if (auto *E = dyn_cast<MemberExpr>(&S)) {
236
+ return true ;
237
+ }
238
+
239
+ bool VisitMemberExpr (MemberExpr *E) {
229
240
// FIXME: should we be using `E->getFoundDecl()`?
230
241
const ValueDecl *VD = E->getMemberDecl ();
231
242
insertIfGlobal (*VD, Referenced.Globals );
232
243
insertIfFunction (*VD, Referenced.Functions );
233
244
if (const auto *FD = dyn_cast<FieldDecl>(VD))
234
245
Referenced.Fields .insert (FD);
235
- } else if (auto *InitList = dyn_cast<InitListExpr>(&S)) {
246
+ return true ;
247
+ }
248
+
249
+ bool VisitInitListExpr (InitListExpr *InitList) {
236
250
if (InitList->getType ()->isRecordType ())
237
251
for (const auto *FD : getFieldsForInitListExpr (InitList))
238
252
Referenced.Fields .insert (FD);
239
- } else if (auto *ParenInitList = dyn_cast<CXXParenListInitExpr>(&S)) {
253
+ return true ;
254
+ }
255
+
256
+ bool VisitCXXParenListInitExpr (CXXParenListInitExpr *ParenInitList) {
240
257
if (ParenInitList->getType ()->isRecordType ())
241
258
for (const auto *FD : getFieldsForInitListExpr (ParenInitList))
242
259
Referenced.Fields .insert (FD);
260
+ return true ;
243
261
}
244
- }
262
+
263
+ private:
264
+ ReferencedDecls &Referenced;
265
+ };
245
266
246
267
ReferencedDecls getReferencedDecls (const FunctionDecl &FD) {
247
268
ReferencedDecls Result;
248
- // Look for global variable and field references in the
249
- // constructor-initializers.
250
- if (const auto *CtorDecl = dyn_cast<CXXConstructorDecl>(&FD)) {
251
- for (const auto *Init : CtorDecl->inits ()) {
252
- if (Init->isMemberInitializer ()) {
253
- Result.Fields .insert (Init->getMember ());
254
- } else if (Init->isIndirectMemberInitializer ()) {
255
- for (const auto *I : Init->getIndirectMember ()->chain ())
256
- Result.Fields .insert (cast<FieldDecl>(I));
257
- }
258
- const Expr *E = Init->getInit ();
259
- assert (E != nullptr );
260
- getReferencedDecls (*E, Result);
261
- }
262
- // Add all fields mentioned in default member initializers.
263
- for (const FieldDecl *F : CtorDecl->getParent ()->fields ())
264
- if (const auto *I = F->getInClassInitializer ())
265
- getReferencedDecls (*I, Result);
266
- }
267
- getReferencedDecls (*FD.getBody (), Result);
269
+ ReferencedDeclsVisitor Visitor (Result);
270
+ Visitor.TraverseStmt (FD.getBody ());
271
+ if (const auto *CtorDecl = dyn_cast<CXXConstructorDecl>(&FD))
272
+ Visitor.TraverseConstructorInits (CtorDecl);
268
273
269
274
return Result;
270
275
}
271
276
272
277
ReferencedDecls getReferencedDecls (const Stmt &S) {
273
278
ReferencedDecls Result;
274
- getReferencedDecls (S, Result);
279
+ ReferencedDeclsVisitor Visitor (Result);
280
+ Visitor.TraverseStmt (const_cast <Stmt *>(&S));
275
281
return Result;
276
282
}
277
283
0 commit comments