@@ -492,7 +492,7 @@ class Gadget {
492
492
#endif
493
493
494
494
virtual bool isWarningGadget () const = 0;
495
- virtual const Stmt * getBaseStmt () const = 0;
495
+ virtual SourceLocation getSourceLoc () const = 0;
496
496
497
497
// / Returns the list of pointer-type variables on which this gadget performs
498
498
// / its operation. Typically, there's only one variable. This isn't a list
@@ -513,6 +513,10 @@ class WarningGadget : public Gadget {
513
513
514
514
static bool classof (const Gadget *G) { return G->isWarningGadget (); }
515
515
bool isWarningGadget () const final { return true ; }
516
+
517
+ virtual void handleUnsafeOperation (UnsafeBufferUsageHandler &Handler,
518
+ bool IsRelatedToDecl,
519
+ ASTContext &Ctx) const = 0;
516
520
};
517
521
518
522
// / Fixable gadgets correspond to code patterns that aren't always unsafe but
@@ -572,7 +576,12 @@ class IncrementGadget : public WarningGadget {
572
576
.bind (OpTag));
573
577
}
574
578
575
- const UnaryOperator *getBaseStmt () const override { return Op; }
579
+ void handleUnsafeOperation (UnsafeBufferUsageHandler &Handler,
580
+ bool IsRelatedToDecl,
581
+ ASTContext &Ctx) const override {
582
+ Handler.handleUnsafeOperation (Op, IsRelatedToDecl, Ctx);
583
+ }
584
+ SourceLocation getSourceLoc () const override { return Op->getBeginLoc (); }
576
585
577
586
DeclUseList getClaimedVarUseSites () const override {
578
587
SmallVector<const DeclRefExpr *, 2 > Uses;
@@ -607,7 +616,12 @@ class DecrementGadget : public WarningGadget {
607
616
.bind (OpTag));
608
617
}
609
618
610
- const UnaryOperator *getBaseStmt () const override { return Op; }
619
+ void handleUnsafeOperation (UnsafeBufferUsageHandler &Handler,
620
+ bool IsRelatedToDecl,
621
+ ASTContext &Ctx) const override {
622
+ Handler.handleUnsafeOperation (Op, IsRelatedToDecl, Ctx);
623
+ }
624
+ SourceLocation getSourceLoc () const override { return Op->getBeginLoc (); }
611
625
612
626
DeclUseList getClaimedVarUseSites () const override {
613
627
if (const auto *DRE =
@@ -648,7 +662,12 @@ class ArraySubscriptGadget : public WarningGadget {
648
662
// clang-format on
649
663
}
650
664
651
- const ArraySubscriptExpr *getBaseStmt () const override { return ASE; }
665
+ void handleUnsafeOperation (UnsafeBufferUsageHandler &Handler,
666
+ bool IsRelatedToDecl,
667
+ ASTContext &Ctx) const override {
668
+ Handler.handleUnsafeOperation (ASE, IsRelatedToDecl, Ctx);
669
+ }
670
+ SourceLocation getSourceLoc () const override { return ASE->getBeginLoc (); }
652
671
653
672
DeclUseList getClaimedVarUseSites () const override {
654
673
if (const auto *DRE =
@@ -696,7 +715,12 @@ class PointerArithmeticGadget : public WarningGadget {
696
715
.bind (PointerArithmeticTag));
697
716
}
698
717
699
- const Stmt *getBaseStmt () const override { return PA; }
718
+ void handleUnsafeOperation (UnsafeBufferUsageHandler &Handler,
719
+ bool IsRelatedToDecl,
720
+ ASTContext &Ctx) const override {
721
+ Handler.handleUnsafeOperation (PA, IsRelatedToDecl, Ctx);
722
+ }
723
+ SourceLocation getSourceLoc () const override { return PA->getBeginLoc (); }
700
724
701
725
DeclUseList getClaimedVarUseSites () const override {
702
726
if (const auto *DRE = dyn_cast<DeclRefExpr>(Ptr->IgnoreParenImpCasts ())) {
@@ -734,7 +758,12 @@ class SpanTwoParamConstructorGadget : public WarningGadget {
734
758
.bind (SpanTwoParamConstructorTag));
735
759
}
736
760
737
- const Stmt *getBaseStmt () const override { return Ctor; }
761
+ void handleUnsafeOperation (UnsafeBufferUsageHandler &Handler,
762
+ bool IsRelatedToDecl,
763
+ ASTContext &Ctx) const override {
764
+ Handler.handleUnsafeOperationInContainer (Ctor, IsRelatedToDecl, Ctx);
765
+ }
766
+ SourceLocation getSourceLoc () const override { return Ctor->getBeginLoc (); }
738
767
739
768
DeclUseList getClaimedVarUseSites () const override {
740
769
// If the constructor call is of the form `std::span{var, n}`, `var` is
@@ -780,11 +809,8 @@ class PointerInitGadget : public FixableGadget {
780
809
781
810
virtual std::optional<FixItList>
782
811
getFixits (const FixitStrategy &S) const override ;
783
-
784
- virtual const Stmt *getBaseStmt () const override {
785
- // FIXME: This needs to be the entire DeclStmt, assuming that this method
786
- // makes sense at all on a FixableGadget.
787
- return PtrInitRHS;
812
+ SourceLocation getSourceLoc () const override {
813
+ return PtrInitRHS->getBeginLoc ();
788
814
}
789
815
790
816
virtual DeclUseList getClaimedVarUseSites () const override {
@@ -833,12 +859,7 @@ class PtrToPtrAssignmentGadget : public FixableGadget {
833
859
834
860
virtual std::optional<FixItList>
835
861
getFixits (const FixitStrategy &S) const override ;
836
-
837
- virtual const Stmt *getBaseStmt () const override {
838
- // FIXME: This should be the binary operator, assuming that this method
839
- // makes sense at all on a FixableGadget.
840
- return PtrLHS;
841
- }
862
+ SourceLocation getSourceLoc () const override { return PtrLHS->getBeginLoc (); }
842
863
843
864
virtual DeclUseList getClaimedVarUseSites () const override {
844
865
return DeclUseList{PtrLHS, PtrRHS};
@@ -888,12 +909,7 @@ class CArrayToPtrAssignmentGadget : public FixableGadget {
888
909
889
910
virtual std::optional<FixItList>
890
911
getFixits (const FixitStrategy &S) const override ;
891
-
892
- virtual const Stmt *getBaseStmt () const override {
893
- // FIXME: This should be the binary operator, assuming that this method
894
- // makes sense at all on a FixableGadget.
895
- return PtrLHS;
896
- }
912
+ SourceLocation getSourceLoc () const override { return PtrLHS->getBeginLoc (); }
897
913
898
914
virtual DeclUseList getClaimedVarUseSites () const override {
899
915
return DeclUseList{PtrLHS, PtrRHS};
@@ -921,10 +937,55 @@ class UnsafeBufferUsageAttrGadget : public WarningGadget {
921
937
}
922
938
923
939
static Matcher matcher () {
924
- return stmt (callExpr (callee (functionDecl (hasAttr (attr::UnsafeBufferUsage))))
925
- .bind (OpTag));
940
+ auto HasUnsafeFnDecl =
941
+ callee (functionDecl (hasAttr (attr::UnsafeBufferUsage)));
942
+ return stmt (callExpr (HasUnsafeFnDecl).bind (OpTag));
943
+ }
944
+
945
+ void handleUnsafeOperation (UnsafeBufferUsageHandler &Handler,
946
+ bool IsRelatedToDecl,
947
+ ASTContext &Ctx) const override {
948
+ Handler.handleUnsafeOperation (Op, IsRelatedToDecl, Ctx);
949
+ }
950
+ SourceLocation getSourceLoc () const override { return Op->getBeginLoc (); }
951
+
952
+ DeclUseList getClaimedVarUseSites () const override { return {}; }
953
+ };
954
+
955
+ // / A call of a constructor that performs unchecked buffer operations
956
+ // / over one of its pointer parameters, or constructs a class object that will
957
+ // / perform buffer operations that depend on the correctness of the parameters.
958
+ class UnsafeBufferUsageCtorAttrGadget : public WarningGadget {
959
+ constexpr static const char *const OpTag = " cxx_construct_expr" ;
960
+ const CXXConstructExpr *Op;
961
+
962
+ public:
963
+ UnsafeBufferUsageCtorAttrGadget (const MatchFinder::MatchResult &Result)
964
+ : WarningGadget(Kind::UnsafeBufferUsageCtorAttr),
965
+ Op (Result.Nodes.getNodeAs<CXXConstructExpr>(OpTag)) {}
966
+
967
+ static bool classof (const Gadget *G) {
968
+ return G->getKind () == Kind::UnsafeBufferUsageCtorAttr;
969
+ }
970
+
971
+ static Matcher matcher () {
972
+ auto HasUnsafeCtorDecl =
973
+ hasDeclaration (cxxConstructorDecl (hasAttr (attr::UnsafeBufferUsage)));
974
+ // std::span(ptr, size) ctor is handled by SpanTwoParamConstructorGadget.
975
+ auto HasTwoParamSpanCtorDecl = hasDeclaration (
976
+ cxxConstructorDecl (hasDeclContext (isInStdNamespace ()), hasName (" span" ),
977
+ parameterCountIs (2 )));
978
+ return stmt (
979
+ cxxConstructExpr (HasUnsafeCtorDecl, unless (HasTwoParamSpanCtorDecl))
980
+ .bind (OpTag));
981
+ }
982
+
983
+ void handleUnsafeOperation (UnsafeBufferUsageHandler &Handler,
984
+ bool IsRelatedToDecl,
985
+ ASTContext &Ctx) const override {
986
+ Handler.handleUnsafeOperation (Op, IsRelatedToDecl, Ctx);
926
987
}
927
- const Stmt * getBaseStmt () const override { return Op; }
988
+ SourceLocation getSourceLoc () const override { return Op-> getBeginLoc () ; }
928
989
929
990
DeclUseList getClaimedVarUseSites () const override { return {}; }
930
991
};
@@ -953,7 +1014,13 @@ class DataInvocationGadget : public WarningGadget {
953
1014
explicitCastExpr (anyOf (has (callExpr), has (parenExpr (has (callExpr)))))
954
1015
.bind (OpTag));
955
1016
}
956
- const Stmt *getBaseStmt () const override { return Op; }
1017
+
1018
+ void handleUnsafeOperation (UnsafeBufferUsageHandler &Handler,
1019
+ bool IsRelatedToDecl,
1020
+ ASTContext &Ctx) const override {
1021
+ Handler.handleUnsafeOperation (Op, IsRelatedToDecl, Ctx);
1022
+ }
1023
+ SourceLocation getSourceLoc () const override { return Op->getBeginLoc (); }
957
1024
958
1025
DeclUseList getClaimedVarUseSites () const override { return {}; }
959
1026
};
@@ -990,8 +1057,7 @@ class ULCArraySubscriptGadget : public FixableGadget {
990
1057
991
1058
virtual std::optional<FixItList>
992
1059
getFixits (const FixitStrategy &S) const override ;
993
-
994
- virtual const Stmt *getBaseStmt () const override { return Node; }
1060
+ SourceLocation getSourceLoc () const override { return Node->getBeginLoc (); }
995
1061
996
1062
virtual DeclUseList getClaimedVarUseSites () const override {
997
1063
if (const auto *DRE =
@@ -1031,8 +1097,7 @@ class UPCStandalonePointerGadget : public FixableGadget {
1031
1097
1032
1098
virtual std::optional<FixItList>
1033
1099
getFixits (const FixitStrategy &S) const override ;
1034
-
1035
- virtual const Stmt *getBaseStmt () const override { return Node; }
1100
+ SourceLocation getSourceLoc () const override { return Node->getBeginLoc (); }
1036
1101
1037
1102
virtual DeclUseList getClaimedVarUseSites () const override { return {Node}; }
1038
1103
};
@@ -1070,10 +1135,9 @@ class PointerDereferenceGadget : public FixableGadget {
1070
1135
return {BaseDeclRefExpr};
1071
1136
}
1072
1137
1073
- virtual const Stmt *getBaseStmt () const final { return Op; }
1074
-
1075
1138
virtual std::optional<FixItList>
1076
1139
getFixits (const FixitStrategy &S) const override ;
1140
+ SourceLocation getSourceLoc () const override { return Op->getBeginLoc (); }
1077
1141
};
1078
1142
1079
1143
// Represents expressions of the form `&DRE[any]` in the Unspecified Pointer
@@ -1108,8 +1172,7 @@ class UPCAddressofArraySubscriptGadget : public FixableGadget {
1108
1172
1109
1173
virtual std::optional<FixItList>
1110
1174
getFixits (const FixitStrategy &) const override ;
1111
-
1112
- virtual const Stmt *getBaseStmt () const override { return Node; }
1175
+ SourceLocation getSourceLoc () const override { return Node->getBeginLoc (); }
1113
1176
1114
1177
virtual DeclUseList getClaimedVarUseSites () const override {
1115
1178
const auto *ArraySubst = cast<ArraySubscriptExpr>(Node->getSubExpr ());
@@ -1218,8 +1281,7 @@ class UPCPreIncrementGadget : public FixableGadget {
1218
1281
1219
1282
virtual std::optional<FixItList>
1220
1283
getFixits (const FixitStrategy &S) const override ;
1221
-
1222
- virtual const Stmt *getBaseStmt () const override { return Node; }
1284
+ SourceLocation getSourceLoc () const override { return Node->getBeginLoc (); }
1223
1285
1224
1286
virtual DeclUseList getClaimedVarUseSites () const override {
1225
1287
return {dyn_cast<DeclRefExpr>(Node->getSubExpr ())};
@@ -1264,8 +1326,7 @@ class UUCAddAssignGadget : public FixableGadget {
1264
1326
1265
1327
virtual std::optional<FixItList>
1266
1328
getFixits (const FixitStrategy &S) const override ;
1267
-
1268
- virtual const Stmt *getBaseStmt () const override { return Node; }
1329
+ SourceLocation getSourceLoc () const override { return Node->getBeginLoc (); }
1269
1330
1270
1331
virtual DeclUseList getClaimedVarUseSites () const override {
1271
1332
return {dyn_cast<DeclRefExpr>(Node->getLHS ())};
@@ -1315,9 +1376,9 @@ class DerefSimplePtrArithFixableGadget : public FixableGadget {
1315
1376
1316
1377
virtual std::optional<FixItList>
1317
1378
getFixits (const FixitStrategy &s) const final ;
1318
-
1319
- // TODO remove this method from FixableGadget interface
1320
- virtual const Stmt * getBaseStmt () const final { return nullptr ; }
1379
+ SourceLocation getSourceLoc () const override {
1380
+ return DerefOp-> getBeginLoc ();
1381
+ }
1321
1382
1322
1383
virtual DeclUseList getClaimedVarUseSites () const final {
1323
1384
return {BaseDeclRefExpr};
@@ -2070,7 +2131,7 @@ UUCAddAssignGadget::getFixits(const FixitStrategy &S) const {
2070
2131
if (S.lookup (VD) == FixitStrategy::Kind::Span) {
2071
2132
FixItList Fixes;
2072
2133
2073
- const Stmt *AddAssignNode = getBaseStmt () ;
2134
+ const Stmt *AddAssignNode = Node ;
2074
2135
StringRef varName = VD->getName ();
2075
2136
const ASTContext &Ctx = VD->getASTContext ();
2076
2137
@@ -2112,20 +2173,19 @@ UPCPreIncrementGadget::getFixits(const FixitStrategy &S) const {
2112
2173
if (S.lookup (VD) == FixitStrategy::Kind::Span) {
2113
2174
FixItList Fixes;
2114
2175
std::stringstream SS;
2115
- const Stmt *PreIncNode = getBaseStmt ();
2116
2176
StringRef varName = VD->getName ();
2117
2177
const ASTContext &Ctx = VD->getASTContext ();
2118
2178
2119
2179
// To transform UPC(++p) to UPC((p = p.subspan(1)).data()):
2120
2180
SS << " (" << varName.data () << " = " << varName.data ()
2121
2181
<< " .subspan(1)).data()" ;
2122
2182
std::optional<SourceLocation> PreIncLocation =
2123
- getEndCharLoc (PreIncNode , Ctx.getSourceManager (), Ctx.getLangOpts ());
2183
+ getEndCharLoc (Node , Ctx.getSourceManager (), Ctx.getLangOpts ());
2124
2184
if (!PreIncLocation)
2125
2185
return std::nullopt;
2126
2186
2127
2187
Fixes.push_back (FixItHint::CreateReplacement (
2128
- SourceRange (PreIncNode ->getBeginLoc (), *PreIncLocation), SS.str ()));
2188
+ SourceRange (Node ->getBeginLoc (), *PreIncLocation), SS.str ()));
2129
2189
return Fixes;
2130
2190
}
2131
2191
}
@@ -2856,7 +2916,7 @@ getFixIts(FixableGadgetSets &FixablesForAllVars, const FixitStrategy &S,
2856
2916
}
2857
2917
#ifndef NDEBUG
2858
2918
Handler.addDebugNoteForVar (
2859
- VD, F->getBaseStmt ()-> getBeginLoc (),
2919
+ VD, F->getSourceLoc (),
2860
2920
(" gadget '" + F->getDebugName () + " ' refused to produce a fix" )
2861
2921
.str ());
2862
2922
#endif
@@ -3008,8 +3068,9 @@ void clang::checkUnsafeBufferUsage(const Decl *D,
3008
3068
// every problematic operation and consider it done. No need to deal
3009
3069
// with fixable gadgets, no need to group operations by variable.
3010
3070
for (const auto &G : WarningGadgets) {
3011
- Handler.handleUnsafeOperation (G->getBaseStmt (), /* IsRelatedToDecl=*/ false ,
3012
- D->getASTContext ());
3071
+ llvm::errs () << " Warnings not EmitSuggestions\n " ;
3072
+ G->handleUnsafeOperation (Handler, /* IsRelatedToDecl=*/ false ,
3073
+ D->getASTContext ());
3013
3074
}
3014
3075
3015
3076
// This return guarantees that most of the machine doesn't run when
@@ -3251,8 +3312,8 @@ void clang::checkUnsafeBufferUsage(const Decl *D,
3251
3312
Tracker, Handler, VarGrpMgr);
3252
3313
3253
3314
for (const auto &G : UnsafeOps.noVar ) {
3254
- Handler. handleUnsafeOperation ( G->getBaseStmt () , /* IsRelatedToDecl=*/ false ,
3255
- D->getASTContext ());
3315
+ G->handleUnsafeOperation (Handler , /* IsRelatedToDecl=*/ false ,
3316
+ D->getASTContext ());
3256
3317
}
3257
3318
3258
3319
for (const auto &[VD, WarningGadgets] : UnsafeOps.byVar ) {
@@ -3263,8 +3324,8 @@ void clang::checkUnsafeBufferUsage(const Decl *D,
3263
3324
: FixItList{},
3264
3325
D, NaiveStrategy);
3265
3326
for (const auto &G : WarningGadgets) {
3266
- Handler. handleUnsafeOperation ( G->getBaseStmt () , /* IsRelatedToDecl=*/ true ,
3267
- D->getASTContext ());
3327
+ G->handleUnsafeOperation (Handler , /* IsRelatedToDecl=*/ true ,
3328
+ D->getASTContext ());
3268
3329
}
3269
3330
}
3270
3331
}
0 commit comments