@@ -1972,14 +1972,18 @@ class DerefSimplePtrArithFixableGadget : public FixableGadget {
1972
1972
};
1973
1973
1974
1974
// / Scan the function and return a list of gadgets found with provided kits.
1975
- static std::tuple<FixableGadgetList, WarningGadgetList, DeclUseTracker>
1976
- findGadgets (const Stmt *S, ASTContext &Ctx,
1977
- const UnsafeBufferUsageHandler &Handler, bool EmitSuggestions) {
1975
+ static void findGadgets (const Stmt *S, ASTContext &Ctx,
1976
+ const UnsafeBufferUsageHandler &Handler,
1977
+ bool EmitSuggestions, FixableGadgetList &FixableGadgets,
1978
+ WarningGadgetList &WarningGadgets,
1979
+ DeclUseTracker &Tracker) {
1978
1980
1979
1981
struct GadgetFinderCallback : MatchFinder::MatchCallback {
1980
- FixableGadgetList FixableGadgets;
1981
- WarningGadgetList WarningGadgets;
1982
- DeclUseTracker Tracker;
1982
+ GadgetFinderCallback (FixableGadgetList &FixableGadgets,
1983
+ WarningGadgetList &WarningGadgets,
1984
+ DeclUseTracker &Tracker)
1985
+ : FixableGadgets(FixableGadgets), WarningGadgets(WarningGadgets),
1986
+ Tracker (Tracker) {}
1983
1987
1984
1988
void run (const MatchFinder::MatchResult &Result) override {
1985
1989
// In debug mode, assert that we've found exactly one gadget.
@@ -2020,10 +2024,14 @@ findGadgets(const Stmt *S, ASTContext &Ctx,
2020
2024
assert (numFound >= 1 && " Gadgets not found in match result!" );
2021
2025
assert (numFound <= 1 && " Conflicting bind tags in gadgets!" );
2022
2026
}
2027
+
2028
+ FixableGadgetList &FixableGadgets;
2029
+ WarningGadgetList &WarningGadgets;
2030
+ DeclUseTracker &Tracker;
2023
2031
};
2024
2032
2025
2033
MatchFinder M;
2026
- GadgetFinderCallback CB;
2034
+ GadgetFinderCallback CB{FixableGadgets, WarningGadgets, Tracker} ;
2027
2035
2028
2036
// clang-format off
2029
2037
M.addMatcher(
@@ -2069,8 +2077,6 @@ findGadgets(const Stmt *S, ASTContext &Ctx,
2069
2077
}
2070
2078
2071
2079
M.match(*S, Ctx);
2072
- return {std::move (CB.FixableGadgets ), std::move (CB.WarningGadgets ),
2073
- std::move (CB.Tracker )};
2074
2080
}
2075
2081
2076
2082
// Compares AST nodes by source locations.
@@ -3896,19 +3902,19 @@ void clang::checkUnsafeBufferUsage(const Decl *D,
3896
3902
3897
3903
SmallVector<Stmt *> Stmts;
3898
3904
3899
- // We do not want to visit a Lambda expression defined inside a method
3900
- // independently. Instead, it should be visited along with the outer method.
3901
- // FIXME: do we want to do the same thing for `BlockDecl`s?
3902
- if (const auto *fd = dyn_cast<CXXMethodDecl>(D)) {
3903
- if (fd->getParent ()->isLambda () && fd->getParent ()->isLocalClass ())
3904
- return ;
3905
- }
3906
-
3907
- // Do not emit fixit suggestions for functions declared in an
3908
- // extern "C" block.
3909
3905
if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
3906
+ // We do not want to visit a Lambda expression defined inside a method
3907
+ // independently. Instead, it should be visited along with the outer method.
3908
+ // FIXME: do we want to do the same thing for `BlockDecl`s?
3909
+ if (const auto *MD = dyn_cast<CXXMethodDecl>(D)) {
3910
+ if (MD->getParent ()->isLambda () && MD->getParent ()->isLocalClass ())
3911
+ return ;
3912
+ }
3913
+
3910
3914
for (FunctionDecl *FReDecl : FD->redecls ()) {
3911
3915
if (FReDecl->isExternC ()) {
3916
+ // Do not emit fixit suggestions for functions declared in an
3917
+ // extern "C" block.
3912
3918
EmitSuggestions = false ;
3913
3919
break ;
3914
3920
}
@@ -3921,26 +3927,29 @@ void clang::checkUnsafeBufferUsage(const Decl *D,
3921
3927
Stmts.push_back (CI->getInit ());
3922
3928
}
3923
3929
}
3924
- }
3925
-
3926
- if (const auto *FD = dyn_cast<FieldDecl>(D)) {
3930
+ } else if (const auto *FlD = dyn_cast<FieldDecl>(D)) {
3927
3931
// Visit in-class initializers for fields.
3928
- if (!FD ->hasInClassInitializer ())
3932
+ if (!FlD ->hasInClassInitializer ())
3929
3933
return ;
3930
-
3931
- Stmts.push_back (FD->getInClassInitializer ());
3932
- }
3933
-
3934
- if (isa<BlockDecl>(D) || isa<ObjCMethodDecl>(D)) {
3934
+ Stmts.push_back (FlD->getInClassInitializer ());
3935
+ // In a FieldDecl there is no function body, there is only a single
3936
+ // statement, and the suggestions machinery is not set up to handle that
3937
+ // kind of structure yet and would give poor suggestions or likely even hit
3938
+ // asserts.
3939
+ EmitSuggestions = false ;
3940
+ } else if (isa<BlockDecl>(D) || isa<ObjCMethodDecl>(D)) {
3935
3941
Stmts.push_back (D->getBody ());
3936
3942
}
3937
3943
3938
3944
assert (!Stmts.empty ());
3939
3945
3946
+ FixableGadgetList FixableGadgets;
3947
+ WarningGadgetList WarningGadgets;
3948
+ DeclUseTracker Tracker;
3940
3949
for (Stmt *S : Stmts) {
3941
- auto [FixableGadgets, WarningGadgets, Tracker] =
3942
- findGadgets (S, D->getASTContext (), Handler, EmitSuggestions);
3943
- applyGadgets (D, std::move (FixableGadgets), std::move (WarningGadgets),
3944
- std::move (Tracker), Handler, EmitSuggestions);
3950
+ findGadgets (S, D->getASTContext (), Handler, EmitSuggestions, FixableGadgets,
3951
+ WarningGadgets, Tracker);
3945
3952
}
3953
+ applyGadgets (D, std::move (FixableGadgets), std::move (WarningGadgets),
3954
+ std::move (Tracker), Handler, EmitSuggestions);
3946
3955
}
0 commit comments