@@ -172,6 +172,12 @@ class MatchDescendantVisitor : public DynamicRecursiveASTVisitor {
172
172
return DynamicRecursiveASTVisitor::TraverseCXXTypeidExpr (Node);
173
173
}
174
174
175
+ bool TraverseCXXDefaultInitExpr (CXXDefaultInitExpr *Node) override {
176
+ if (!TraverseStmt (Node->getExpr ()))
177
+ return false ;
178
+ return DynamicRecursiveASTVisitor::TraverseCXXDefaultInitExpr (Node);
179
+ }
180
+
175
181
bool TraverseStmt (Stmt *Node) override {
176
182
if (!Node)
177
183
return true ;
@@ -1987,14 +1993,18 @@ class DerefSimplePtrArithFixableGadget : public FixableGadget {
1987
1993
};
1988
1994
1989
1995
// / 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) {
1993
2001
1994
2002
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) {}
1998
2008
1999
2009
void run (const MatchFinder::MatchResult &Result) override {
2000
2010
// In debug mode, assert that we've found exactly one gadget.
@@ -2035,10 +2045,14 @@ findGadgets(const Decl *D, const UnsafeBufferUsageHandler &Handler,
2035
2045
assert (numFound >= 1 && " Gadgets not found in match result!" );
2036
2046
assert (numFound <= 1 && " Conflicting bind tags in gadgets!" );
2037
2047
}
2048
+
2049
+ FixableGadgetList &FixableGadgets;
2050
+ WarningGadgetList &WarningGadgets;
2051
+ DeclUseTracker &Tracker;
2038
2052
};
2039
2053
2040
2054
MatchFinder M;
2041
- GadgetFinderCallback CB;
2055
+ GadgetFinderCallback CB{FixableGadgets, WarningGadgets, Tracker} ;
2042
2056
2043
2057
// clang-format off
2044
2058
M.addMatcher(
@@ -2083,9 +2097,7 @@ findGadgets(const Decl *D, const UnsafeBufferUsageHandler &Handler,
2083
2097
// clang-format on
2084
2098
}
2085
2099
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);
2089
2101
}
2090
2102
2091
2103
// Compares AST nodes by source locations.
@@ -3630,39 +3642,9 @@ class VariableGroupsManagerImpl : public VariableGroupsManager {
3630
3642
}
3631
3643
};
3632
3644
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) {
3666
3648
if (!EmitSuggestions) {
3667
3649
// Our job is very easy without suggestions. Just warn about
3668
3650
// every problematic operation and consider it done. No need to deal
@@ -3706,8 +3688,10 @@ void clang::checkUnsafeBufferUsage(const Decl *D,
3706
3688
if (WarningGadgets.empty ())
3707
3689
return ;
3708
3690
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));
3711
3695
3712
3696
std::map<const VarDecl *, FixItList> FixItsForVariableGroup;
3713
3697
@@ -3928,3 +3912,56 @@ void clang::checkUnsafeBufferUsage(const Decl *D,
3928
3912
}
3929
3913
}
3930
3914
}
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