@@ -172,6 +172,12 @@ class MatchDescendantVisitor : public DynamicRecursiveASTVisitor {
172172 return DynamicRecursiveASTVisitor::TraverseCXXTypeidExpr (Node);
173173 }
174174
175+ bool TraverseCXXDefaultInitExpr (CXXDefaultInitExpr *Node) override {
176+ if (!TraverseStmt (Node->getExpr ()))
177+ return false ;
178+ return DynamicRecursiveASTVisitor::TraverseCXXDefaultInitExpr (Node);
179+ }
180+
175181 bool TraverseStmt (Stmt *Node) override {
176182 if (!Node)
177183 return true ;
@@ -1987,14 +1993,18 @@ class DerefSimplePtrArithFixableGadget : public FixableGadget {
19871993};
19881994
19891995// / Scan the function and return a list of gadgets found with provided kits.
1990- static std::tuple<FixableGadgetList, WarningGadgetList, DeclUseTracker>
1991- findGadgets (const Decl *D, const UnsafeBufferUsageHandler &Handler,
1992- bool EmitSuggestions) {
1996+ static void findGadgets (const Stmt *S, ASTContext &Ctx,
1997+ const UnsafeBufferUsageHandler &Handler,
1998+ bool EmitSuggestions, FixableGadgetList &FixableGadgets,
1999+ WarningGadgetList &WarningGadgets,
2000+ DeclUseTracker &Tracker) {
19932001
19942002 struct GadgetFinderCallback : MatchFinder::MatchCallback {
1995- FixableGadgetList FixableGadgets;
1996- WarningGadgetList WarningGadgets;
1997- DeclUseTracker Tracker;
2003+ GadgetFinderCallback (FixableGadgetList &FixableGadgets,
2004+ WarningGadgetList &WarningGadgets,
2005+ DeclUseTracker &Tracker)
2006+ : FixableGadgets(FixableGadgets), WarningGadgets(WarningGadgets),
2007+ Tracker (Tracker) {}
19982008
19992009 void run (const MatchFinder::MatchResult &Result) override {
20002010 // In debug mode, assert that we've found exactly one gadget.
@@ -2035,10 +2045,14 @@ findGadgets(const Decl *D, const UnsafeBufferUsageHandler &Handler,
20352045 assert (numFound >= 1 && " Gadgets not found in match result!" );
20362046 assert (numFound <= 1 && " Conflicting bind tags in gadgets!" );
20372047 }
2048+
2049+ FixableGadgetList &FixableGadgets;
2050+ WarningGadgetList &WarningGadgets;
2051+ DeclUseTracker &Tracker;
20382052 };
20392053
20402054 MatchFinder M;
2041- GadgetFinderCallback CB;
2055+ GadgetFinderCallback CB{FixableGadgets, WarningGadgets, Tracker} ;
20422056
20432057 // clang-format off
20442058 M.addMatcher(
@@ -2083,9 +2097,7 @@ findGadgets(const Decl *D, const UnsafeBufferUsageHandler &Handler,
20832097 // clang-format on
20842098 }
20852099
2086- M.match (*D->getBody (), D->getASTContext ());
2087- return {std::move (CB.FixableGadgets ), std::move (CB.WarningGadgets ),
2088- std::move (CB.Tracker )};
2100+ M.match(*S, Ctx);
20892101}
20902102
20912103// Compares AST nodes by source locations.
@@ -3630,39 +3642,9 @@ class VariableGroupsManagerImpl : public VariableGroupsManager {
36303642 }
36313643};
36323644
3633- void clang::checkUnsafeBufferUsage (const Decl *D,
3634- UnsafeBufferUsageHandler &Handler,
3635- bool EmitSuggestions) {
3636- #ifndef NDEBUG
3637- Handler.clearDebugNotes ();
3638- #endif
3639-
3640- assert (D && D->getBody ());
3641- // We do not want to visit a Lambda expression defined inside a method
3642- // independently. Instead, it should be visited along with the outer method.
3643- // FIXME: do we want to do the same thing for `BlockDecl`s?
3644- if (const auto *fd = dyn_cast<CXXMethodDecl>(D)) {
3645- if (fd->getParent ()->isLambda () && fd->getParent ()->isLocalClass ())
3646- return ;
3647- }
3648-
3649- // Do not emit fixit suggestions for functions declared in an
3650- // extern "C" block.
3651- if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
3652- for (FunctionDecl *FReDecl : FD->redecls ()) {
3653- if (FReDecl->isExternC ()) {
3654- EmitSuggestions = false ;
3655- break ;
3656- }
3657- }
3658- }
3659-
3660- WarningGadgetSets UnsafeOps;
3661- FixableGadgetSets FixablesForAllVars;
3662-
3663- auto [FixableGadgets, WarningGadgets, Tracker] =
3664- findGadgets (D, Handler, EmitSuggestions);
3665-
3645+ void applyGadgets (const Decl *D, FixableGadgetList FixableGadgets,
3646+ WarningGadgetList WarningGadgets, DeclUseTracker Tracker,
3647+ UnsafeBufferUsageHandler &Handler, bool EmitSuggestions) {
36663648 if (!EmitSuggestions) {
36673649 // Our job is very easy without suggestions. Just warn about
36683650 // every problematic operation and consider it done. No need to deal
@@ -3706,8 +3688,10 @@ void clang::checkUnsafeBufferUsage(const Decl *D,
37063688 if (WarningGadgets.empty ())
37073689 return ;
37083690
3709- UnsafeOps = groupWarningGadgetsByVar (std::move (WarningGadgets));
3710- FixablesForAllVars = groupFixablesByVar (std::move (FixableGadgets));
3691+ WarningGadgetSets UnsafeOps =
3692+ groupWarningGadgetsByVar (std::move (WarningGadgets));
3693+ FixableGadgetSets FixablesForAllVars =
3694+ groupFixablesByVar (std::move (FixableGadgets));
37113695
37123696 std::map<const VarDecl *, FixItList> FixItsForVariableGroup;
37133697
@@ -3928,3 +3912,56 @@ void clang::checkUnsafeBufferUsage(const Decl *D,
39283912 }
39293913 }
39303914}
3915+
3916+ void clang::checkUnsafeBufferUsage (const Decl *D,
3917+ UnsafeBufferUsageHandler &Handler,
3918+ bool EmitSuggestions) {
3919+ #ifndef NDEBUG
3920+ Handler.clearDebugNotes ();
3921+ #endif
3922+
3923+ assert (D);
3924+
3925+ SmallVector<Stmt *> Stmts;
3926+
3927+ if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
3928+ // We do not want to visit a Lambda expression defined inside a method
3929+ // independently. Instead, it should be visited along with the outer method.
3930+ // FIXME: do we want to do the same thing for `BlockDecl`s?
3931+ if (const auto *MD = dyn_cast<CXXMethodDecl>(D)) {
3932+ if (MD->getParent ()->isLambda () && MD->getParent ()->isLocalClass ())
3933+ return ;
3934+ }
3935+
3936+ for (FunctionDecl *FReDecl : FD->redecls ()) {
3937+ if (FReDecl->isExternC ()) {
3938+ // Do not emit fixit suggestions for functions declared in an
3939+ // extern "C" block.
3940+ EmitSuggestions = false ;
3941+ break ;
3942+ }
3943+ }
3944+
3945+ Stmts.push_back (FD->getBody ());
3946+
3947+ if (const auto *ID = dyn_cast<CXXConstructorDecl>(D)) {
3948+ for (const CXXCtorInitializer *CI : ID->inits ()) {
3949+ Stmts.push_back (CI->getInit ());
3950+ }
3951+ }
3952+ } else if (isa<BlockDecl>(D) || isa<ObjCMethodDecl>(D)) {
3953+ Stmts.push_back (D->getBody ());
3954+ }
3955+
3956+ assert (!Stmts.empty ());
3957+
3958+ FixableGadgetList FixableGadgets;
3959+ WarningGadgetList WarningGadgets;
3960+ DeclUseTracker Tracker;
3961+ for (Stmt *S : Stmts) {
3962+ findGadgets (S, D->getASTContext (), Handler, EmitSuggestions, FixableGadgets,
3963+ WarningGadgets, Tracker);
3964+ }
3965+ applyGadgets (D, std::move (FixableGadgets), std::move (WarningGadgets),
3966+ std::move (Tracker), Handler, EmitSuggestions);
3967+ }
0 commit comments