@@ -1386,14 +1386,18 @@ class DerefSimplePtrArithFixableGadget : public FixableGadget {
1386
1386
};
1387
1387
1388
1388
// / Scan the function and return a list of gadgets found with provided kits.
1389
- static std::tuple<FixableGadgetList, WarningGadgetList, DeclUseTracker>
1390
- findGadgets (const Stmt *S, ASTContext &Ctx,
1391
- const UnsafeBufferUsageHandler &Handler, bool EmitSuggestions) {
1389
+ static void findGadgets (const Stmt *S, ASTContext &Ctx,
1390
+ const UnsafeBufferUsageHandler &Handler,
1391
+ bool EmitSuggestions, FixableGadgetList &FixableGadgets,
1392
+ WarningGadgetList &WarningGadgets,
1393
+ DeclUseTracker &Tracker) {
1392
1394
1393
1395
struct GadgetFinderCallback : MatchFinder::MatchCallback {
1394
- FixableGadgetList FixableGadgets;
1395
- WarningGadgetList WarningGadgets;
1396
- DeclUseTracker Tracker;
1396
+ GadgetFinderCallback (FixableGadgetList &FixableGadgets,
1397
+ WarningGadgetList &WarningGadgets,
1398
+ DeclUseTracker &Tracker)
1399
+ : FixableGadgets(FixableGadgets), WarningGadgets(WarningGadgets),
1400
+ Tracker (Tracker) {}
1397
1401
1398
1402
void run (const MatchFinder::MatchResult &Result) override {
1399
1403
// In debug mode, assert that we've found exactly one gadget.
@@ -1434,10 +1438,14 @@ findGadgets(const Stmt *S, ASTContext &Ctx,
1434
1438
assert (numFound >= 1 && " Gadgets not found in match result!" );
1435
1439
assert (numFound <= 1 && " Conflicting bind tags in gadgets!" );
1436
1440
}
1441
+
1442
+ FixableGadgetList &FixableGadgets;
1443
+ WarningGadgetList &WarningGadgets;
1444
+ DeclUseTracker &Tracker;
1437
1445
};
1438
1446
1439
1447
MatchFinder M;
1440
- GadgetFinderCallback CB;
1448
+ GadgetFinderCallback CB{FixableGadgets, WarningGadgets, Tracker} ;
1441
1449
1442
1450
// clang-format off
1443
1451
M.addMatcher(
@@ -1484,8 +1492,6 @@ findGadgets(const Stmt *S, ASTContext &Ctx,
1484
1492
}
1485
1493
1486
1494
M.match(*S, Ctx);
1487
- return {std::move (CB.FixableGadgets ), std::move (CB.WarningGadgets ),
1488
- std::move (CB.Tracker )};
1489
1495
}
1490
1496
1491
1497
// Compares AST nodes by source locations.
@@ -3312,19 +3318,19 @@ void clang::checkUnsafeBufferUsage(const Decl *D,
3312
3318
3313
3319
SmallVector<Stmt *> Stmts;
3314
3320
3315
- // We do not want to visit a Lambda expression defined inside a method
3316
- // independently. Instead, it should be visited along with the outer method.
3317
- // FIXME: do we want to do the same thing for `BlockDecl`s?
3318
- if (const auto *fd = dyn_cast<CXXMethodDecl>(D)) {
3319
- if (fd->getParent ()->isLambda () && fd->getParent ()->isLocalClass ())
3320
- return ;
3321
- }
3322
-
3323
- // Do not emit fixit suggestions for functions declared in an
3324
- // extern "C" block.
3325
3321
if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
3322
+ // We do not want to visit a Lambda expression defined inside a method
3323
+ // independently. Instead, it should be visited along with the outer method.
3324
+ // FIXME: do we want to do the same thing for `BlockDecl`s?
3325
+ if (const auto *MD = dyn_cast<CXXMethodDecl>(D)) {
3326
+ if (MD->getParent ()->isLambda () && MD->getParent ()->isLocalClass ())
3327
+ return ;
3328
+ }
3329
+
3326
3330
for (FunctionDecl *FReDecl : FD->redecls ()) {
3327
3331
if (FReDecl->isExternC ()) {
3332
+ // Do not emit fixit suggestions for functions declared in an
3333
+ // extern "C" block.
3328
3334
EmitSuggestions = false ;
3329
3335
break ;
3330
3336
}
@@ -3337,26 +3343,29 @@ void clang::checkUnsafeBufferUsage(const Decl *D,
3337
3343
Stmts.push_back (CI->getInit ());
3338
3344
}
3339
3345
}
3340
- }
3341
-
3342
- if (const auto *FD = dyn_cast<FieldDecl>(D)) {
3346
+ } else if (const auto *FlD = dyn_cast<FieldDecl>(D)) {
3343
3347
// Visit in-class initializers for fields.
3344
- if (!FD ->hasInClassInitializer ())
3348
+ if (!FlD ->hasInClassInitializer ())
3345
3349
return ;
3346
-
3347
- Stmts.push_back (FD->getInClassInitializer ());
3348
- }
3349
-
3350
- if (isa<BlockDecl>(D) || isa<ObjCMethodDecl>(D)) {
3350
+ Stmts.push_back (FlD->getInClassInitializer ());
3351
+ // In a FieldDecl there is no function body, there is only a single
3352
+ // statement, and the suggestions machinery is not set up to handle that
3353
+ // kind of structure yet and would give poor suggestions or likely even hit
3354
+ // asserts.
3355
+ EmitSuggestions = false ;
3356
+ } else if (isa<BlockDecl>(D) || isa<ObjCMethodDecl>(D)) {
3351
3357
Stmts.push_back (D->getBody ());
3352
3358
}
3353
3359
3354
3360
assert (!Stmts.empty ());
3355
3361
3362
+ FixableGadgetList FixableGadgets;
3363
+ WarningGadgetList WarningGadgets;
3364
+ DeclUseTracker Tracker;
3356
3365
for (Stmt *S : Stmts) {
3357
- auto [FixableGadgets, WarningGadgets, Tracker] =
3358
- findGadgets (S, D->getASTContext (), Handler, EmitSuggestions);
3359
- applyGadgets (D, std::move (FixableGadgets), std::move (WarningGadgets),
3360
- std::move (Tracker), Handler, EmitSuggestions);
3366
+ findGadgets (S, D->getASTContext (), Handler, EmitSuggestions, FixableGadgets,
3367
+ WarningGadgets, Tracker);
3361
3368
}
3369
+ applyGadgets (D, std::move (FixableGadgets), std::move (WarningGadgets),
3370
+ std::move (Tracker), Handler, EmitSuggestions);
3362
3371
}
0 commit comments