[clang] Warning for unsafe invocation of span::data (PR #75650)
https://github.com/t-rasmud approved this pull request. LGTM! https://github.com/llvm/llvm-project/pull/75650 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [-Wunsafe-buffer-usage] Add a subgroup `-Wunsafe-buffer-usage-in-container` (PR #75665)
https://github.com/t-rasmud approved this pull request. https://github.com/llvm/llvm-project/pull/75665 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] Warning for unsafe invocation of span::data (PR #75650)
https://github.com/t-rasmud requested changes to this pull request. https://github.com/llvm/llvm-project/pull/75650 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] Warning for unsafe invocation of span::data (PR #75650)
https://github.com/t-rasmud edited https://github.com/llvm/llvm-project/pull/75650 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] Warning for unsafe invocation of span::data (PR #75650)
@@ -721,6 +721,33 @@ class UnsafeBufferUsageAttrGadget : public WarningGadget { DeclUseList getClaimedVarUseSites() const override { return {}; } }; +// Warning gadget for unsafe invocation of span::data method. +// Triggers when the pointer returned by the invocation is immediately +// cast to a larger type. + +class DataInvocationGadget : public WarningGadget { + constexpr static const char *const OpTag = "data_invocation_expr"; + const ExplicitCastExpr *Op; + + public: + DataInvocationGadget(const MatchFinder::MatchResult ) + : WarningGadget(Kind::DataInvocation), +Op(Result.Nodes.getNodeAs(OpTag)) {} + + static bool classof(const Gadget *G) { +return G->getKind() == Kind::DataInvocation; + } + + static Matcher matcher() { +return stmt( +explicitCastExpr(has(cxxMemberCallExpr(callee( + cxxMethodDecl(hasName("data")).bind(OpTag)); t-rasmud wrote: Will this also match on user defined functions called "data"? I think something like `cxxMethodDecl(ofClass(hasName("span")))` might be needed to match `span.data()` alone (but I might be wrong). In any case, maybe have a test case with a user defined function called "data" which'll show the matcher matches only on `span.data()`. https://github.com/llvm/llvm-project/pull/75650 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [-Wunsafe-buffer-usage] Add FixableGadget for AddAssign in UnspecifiedUntypedContext (PR #71862)
https://github.com/t-rasmud closed https://github.com/llvm/llvm-project/pull/71862 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [-Wunsafe-buffer-usage] Add FixableGadget for AddAssign in UnspecifiedUntypedContext (PR #71862)
https://github.com/t-rasmud updated https://github.com/llvm/llvm-project/pull/71862 >From 6636745d1c444747a33c91b366a730d81ca5db5a Mon Sep 17 00:00:00 2001 From: Rashmi Mudduluru Date: Wed, 1 Nov 2023 13:43:12 -0700 Subject: [PATCH 01/14] [-Wunsafe-buffer-usage][WIP] Fixable gadget for AddAssign --- .../Analyses/UnsafeBufferUsageGadgets.def | 1 + clang/lib/Analysis/UnsafeBufferUsage.cpp | 65 +++ ...-unsafe-buffer-usage-fixits-add-assign.cpp | 38 +++ 3 files changed, 104 insertions(+) create mode 100644 clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-add-assign.cpp diff --git a/clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def b/clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def index ff687a0d178bdea..757ee452ced7488 100644 --- a/clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def +++ b/clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def @@ -36,6 +36,7 @@ FIXABLE_GADGET(PointerDereference) FIXABLE_GADGET(UPCAddressofArraySubscript) // '[any]' in an Unspecified Pointer Context FIXABLE_GADGET(UPCStandalonePointer) FIXABLE_GADGET(UPCPreIncrement)// '++Ptr' in an Unspecified Pointer Context +FIXABLE_GADGET(UUCAddAssign)// 'Ptr += n' in an Unspecified Untyped Context FIXABLE_GADGET(PointerAssignment) FIXABLE_GADGET(PointerInit) diff --git a/clang/lib/Analysis/UnsafeBufferUsage.cpp b/clang/lib/Analysis/UnsafeBufferUsage.cpp index e332a3609290aac..7b79f5360c79d6e 100644 --- a/clang/lib/Analysis/UnsafeBufferUsage.cpp +++ b/clang/lib/Analysis/UnsafeBufferUsage.cpp @@ -1028,6 +1028,42 @@ class UPCPreIncrementGadget : public FixableGadget { } }; +// Representing a pointer type expression of the form `Ptr += n` in an +// Unspecified Untyped Context (UUC): +class UUCAddAssignGadget : public FixableGadget { +private: + static constexpr const char *const UUCAddAssignTag = +"PointerAddAssignUnderUUC"; + const BinaryOperator *Node; // the `Ptr += n` node + +public: + UUCAddAssignGadget(const MatchFinder::MatchResult ) +: FixableGadget(Kind::UUCAddAssign), + Node(Result.Nodes.getNodeAs(UUCAddAssignTag)) { +assert(Node != nullptr && "Expecting a non-null matching result"); + } + + static bool classof(const Gadget *G) { +return G->getKind() == Kind::UUCAddAssign; + } + + static Matcher matcher() { +return stmt(isInUnspecifiedUntypedContext(expr(ignoringImpCasts( +binaryOperator(hasOperatorName("+="), + hasLHS(declRefExpr( +toSupportedVariable())) + ).bind(UUCAddAssignTag); + } + + virtual std::optional getFixits(const Strategy ) const override; + + virtual const Stmt *getBaseStmt() const override { return Node; } + + virtual DeclUseList getClaimedVarUseSites() const override { +return {dyn_cast(Node->getLHS())}; + } +}; + // Representing a fixable expression of the form `*(ptr + 123)` or `*(123 + // ptr)`: class DerefSimplePtrArithFixableGadget : public FixableGadget { @@ -1766,6 +1802,35 @@ fixUPCAddressofArraySubscriptWithSpan(const UnaryOperator *Node) { FixItHint::CreateReplacement(Node->getSourceRange(), SS.str())}; } +std::optional UUCAddAssignGadget::getFixits(const Strategy ) const { + DeclUseList DREs = getClaimedVarUseSites(); + + if (DREs.size() != 1) +return std::nullopt; // In cases of `Ptr += n` where `Ptr` is not a DRE, we + // give up + if (const VarDecl *VD = dyn_cast(DREs.front()->getDecl())) { +if (S.lookup(VD) == Strategy::Kind::Span) { + FixItList Fixes; + std::stringstream SS; + const Stmt *AddAssignNode = getBaseStmt(); + StringRef varName = VD->getName(); + const ASTContext = VD->getASTContext(); + + // To transform UUC(p += n) to UUC((p = p.subspan(1)).data()): + SS << varName.data() << " = " << varName.data() + << ".subspan(" << getUserFillPlaceHolder() << ")"; + std::optional AddAssignLocation = + getEndCharLoc(AddAssignNode, Ctx.getSourceManager(), Ctx.getLangOpts()); + if (!AddAssignLocation) +return std::nullopt; + + Fixes.push_back(FixItHint::CreateReplacement( + SourceRange(AddAssignNode->getBeginLoc(), *AddAssignLocation), SS.str())); + return Fixes; +} + } + return std::nullopt; // Not in the cases that we can handle for now, give up. +} std::optional UPCPreIncrementGadget::getFixits(const Strategy ) const { DeclUseList DREs = getClaimedVarUseSites(); diff --git a/clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-add-assign.cpp b/clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-add-assign.cpp new file mode 100644 index 000..e2b9a43dee9b3c3 --- /dev/null +++ b/clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-add-assign.cpp @@ -0,0 +1,38 @@ +// RUN: %clang_cc1 -std=c++20 -Wunsafe-buffer-usage \ +// RUN:
[clang] [-Wunsafe-buffer-usage] Add FixableGadget for AddAssign in UnspecifiedUntypedContext (PR #71862)
https://github.com/t-rasmud updated https://github.com/llvm/llvm-project/pull/71862 >From 6636745d1c444747a33c91b366a730d81ca5db5a Mon Sep 17 00:00:00 2001 From: Rashmi Mudduluru Date: Wed, 1 Nov 2023 13:43:12 -0700 Subject: [PATCH 01/13] [-Wunsafe-buffer-usage][WIP] Fixable gadget for AddAssign --- .../Analyses/UnsafeBufferUsageGadgets.def | 1 + clang/lib/Analysis/UnsafeBufferUsage.cpp | 65 +++ ...-unsafe-buffer-usage-fixits-add-assign.cpp | 38 +++ 3 files changed, 104 insertions(+) create mode 100644 clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-add-assign.cpp diff --git a/clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def b/clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def index ff687a0d178bdea..757ee452ced7488 100644 --- a/clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def +++ b/clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def @@ -36,6 +36,7 @@ FIXABLE_GADGET(PointerDereference) FIXABLE_GADGET(UPCAddressofArraySubscript) // '[any]' in an Unspecified Pointer Context FIXABLE_GADGET(UPCStandalonePointer) FIXABLE_GADGET(UPCPreIncrement)// '++Ptr' in an Unspecified Pointer Context +FIXABLE_GADGET(UUCAddAssign)// 'Ptr += n' in an Unspecified Untyped Context FIXABLE_GADGET(PointerAssignment) FIXABLE_GADGET(PointerInit) diff --git a/clang/lib/Analysis/UnsafeBufferUsage.cpp b/clang/lib/Analysis/UnsafeBufferUsage.cpp index e332a3609290aac..7b79f5360c79d6e 100644 --- a/clang/lib/Analysis/UnsafeBufferUsage.cpp +++ b/clang/lib/Analysis/UnsafeBufferUsage.cpp @@ -1028,6 +1028,42 @@ class UPCPreIncrementGadget : public FixableGadget { } }; +// Representing a pointer type expression of the form `Ptr += n` in an +// Unspecified Untyped Context (UUC): +class UUCAddAssignGadget : public FixableGadget { +private: + static constexpr const char *const UUCAddAssignTag = +"PointerAddAssignUnderUUC"; + const BinaryOperator *Node; // the `Ptr += n` node + +public: + UUCAddAssignGadget(const MatchFinder::MatchResult ) +: FixableGadget(Kind::UUCAddAssign), + Node(Result.Nodes.getNodeAs(UUCAddAssignTag)) { +assert(Node != nullptr && "Expecting a non-null matching result"); + } + + static bool classof(const Gadget *G) { +return G->getKind() == Kind::UUCAddAssign; + } + + static Matcher matcher() { +return stmt(isInUnspecifiedUntypedContext(expr(ignoringImpCasts( +binaryOperator(hasOperatorName("+="), + hasLHS(declRefExpr( +toSupportedVariable())) + ).bind(UUCAddAssignTag); + } + + virtual std::optional getFixits(const Strategy ) const override; + + virtual const Stmt *getBaseStmt() const override { return Node; } + + virtual DeclUseList getClaimedVarUseSites() const override { +return {dyn_cast(Node->getLHS())}; + } +}; + // Representing a fixable expression of the form `*(ptr + 123)` or `*(123 + // ptr)`: class DerefSimplePtrArithFixableGadget : public FixableGadget { @@ -1766,6 +1802,35 @@ fixUPCAddressofArraySubscriptWithSpan(const UnaryOperator *Node) { FixItHint::CreateReplacement(Node->getSourceRange(), SS.str())}; } +std::optional UUCAddAssignGadget::getFixits(const Strategy ) const { + DeclUseList DREs = getClaimedVarUseSites(); + + if (DREs.size() != 1) +return std::nullopt; // In cases of `Ptr += n` where `Ptr` is not a DRE, we + // give up + if (const VarDecl *VD = dyn_cast(DREs.front()->getDecl())) { +if (S.lookup(VD) == Strategy::Kind::Span) { + FixItList Fixes; + std::stringstream SS; + const Stmt *AddAssignNode = getBaseStmt(); + StringRef varName = VD->getName(); + const ASTContext = VD->getASTContext(); + + // To transform UUC(p += n) to UUC((p = p.subspan(1)).data()): + SS << varName.data() << " = " << varName.data() + << ".subspan(" << getUserFillPlaceHolder() << ")"; + std::optional AddAssignLocation = + getEndCharLoc(AddAssignNode, Ctx.getSourceManager(), Ctx.getLangOpts()); + if (!AddAssignLocation) +return std::nullopt; + + Fixes.push_back(FixItHint::CreateReplacement( + SourceRange(AddAssignNode->getBeginLoc(), *AddAssignLocation), SS.str())); + return Fixes; +} + } + return std::nullopt; // Not in the cases that we can handle for now, give up. +} std::optional UPCPreIncrementGadget::getFixits(const Strategy ) const { DeclUseList DREs = getClaimedVarUseSites(); diff --git a/clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-add-assign.cpp b/clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-add-assign.cpp new file mode 100644 index 000..e2b9a43dee9b3c3 --- /dev/null +++ b/clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-add-assign.cpp @@ -0,0 +1,38 @@ +// RUN: %clang_cc1 -std=c++20 -Wunsafe-buffer-usage \ +// RUN:
[clang] [-Wunsafe-buffer-usage] Add FixableGadget for AddAssign in UnspecifiedUntypedContext (PR #71862)
https://github.com/t-rasmud updated https://github.com/llvm/llvm-project/pull/71862 >From 6636745d1c444747a33c91b366a730d81ca5db5a Mon Sep 17 00:00:00 2001 From: Rashmi Mudduluru Date: Wed, 1 Nov 2023 13:43:12 -0700 Subject: [PATCH 01/12] [-Wunsafe-buffer-usage][WIP] Fixable gadget for AddAssign --- .../Analyses/UnsafeBufferUsageGadgets.def | 1 + clang/lib/Analysis/UnsafeBufferUsage.cpp | 65 +++ ...-unsafe-buffer-usage-fixits-add-assign.cpp | 38 +++ 3 files changed, 104 insertions(+) create mode 100644 clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-add-assign.cpp diff --git a/clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def b/clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def index ff687a0d178bdea..757ee452ced7488 100644 --- a/clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def +++ b/clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def @@ -36,6 +36,7 @@ FIXABLE_GADGET(PointerDereference) FIXABLE_GADGET(UPCAddressofArraySubscript) // '[any]' in an Unspecified Pointer Context FIXABLE_GADGET(UPCStandalonePointer) FIXABLE_GADGET(UPCPreIncrement)// '++Ptr' in an Unspecified Pointer Context +FIXABLE_GADGET(UUCAddAssign)// 'Ptr += n' in an Unspecified Untyped Context FIXABLE_GADGET(PointerAssignment) FIXABLE_GADGET(PointerInit) diff --git a/clang/lib/Analysis/UnsafeBufferUsage.cpp b/clang/lib/Analysis/UnsafeBufferUsage.cpp index e332a3609290aac..7b79f5360c79d6e 100644 --- a/clang/lib/Analysis/UnsafeBufferUsage.cpp +++ b/clang/lib/Analysis/UnsafeBufferUsage.cpp @@ -1028,6 +1028,42 @@ class UPCPreIncrementGadget : public FixableGadget { } }; +// Representing a pointer type expression of the form `Ptr += n` in an +// Unspecified Untyped Context (UUC): +class UUCAddAssignGadget : public FixableGadget { +private: + static constexpr const char *const UUCAddAssignTag = +"PointerAddAssignUnderUUC"; + const BinaryOperator *Node; // the `Ptr += n` node + +public: + UUCAddAssignGadget(const MatchFinder::MatchResult ) +: FixableGadget(Kind::UUCAddAssign), + Node(Result.Nodes.getNodeAs(UUCAddAssignTag)) { +assert(Node != nullptr && "Expecting a non-null matching result"); + } + + static bool classof(const Gadget *G) { +return G->getKind() == Kind::UUCAddAssign; + } + + static Matcher matcher() { +return stmt(isInUnspecifiedUntypedContext(expr(ignoringImpCasts( +binaryOperator(hasOperatorName("+="), + hasLHS(declRefExpr( +toSupportedVariable())) + ).bind(UUCAddAssignTag); + } + + virtual std::optional getFixits(const Strategy ) const override; + + virtual const Stmt *getBaseStmt() const override { return Node; } + + virtual DeclUseList getClaimedVarUseSites() const override { +return {dyn_cast(Node->getLHS())}; + } +}; + // Representing a fixable expression of the form `*(ptr + 123)` or `*(123 + // ptr)`: class DerefSimplePtrArithFixableGadget : public FixableGadget { @@ -1766,6 +1802,35 @@ fixUPCAddressofArraySubscriptWithSpan(const UnaryOperator *Node) { FixItHint::CreateReplacement(Node->getSourceRange(), SS.str())}; } +std::optional UUCAddAssignGadget::getFixits(const Strategy ) const { + DeclUseList DREs = getClaimedVarUseSites(); + + if (DREs.size() != 1) +return std::nullopt; // In cases of `Ptr += n` where `Ptr` is not a DRE, we + // give up + if (const VarDecl *VD = dyn_cast(DREs.front()->getDecl())) { +if (S.lookup(VD) == Strategy::Kind::Span) { + FixItList Fixes; + std::stringstream SS; + const Stmt *AddAssignNode = getBaseStmt(); + StringRef varName = VD->getName(); + const ASTContext = VD->getASTContext(); + + // To transform UUC(p += n) to UUC((p = p.subspan(1)).data()): + SS << varName.data() << " = " << varName.data() + << ".subspan(" << getUserFillPlaceHolder() << ")"; + std::optional AddAssignLocation = + getEndCharLoc(AddAssignNode, Ctx.getSourceManager(), Ctx.getLangOpts()); + if (!AddAssignLocation) +return std::nullopt; + + Fixes.push_back(FixItHint::CreateReplacement( + SourceRange(AddAssignNode->getBeginLoc(), *AddAssignLocation), SS.str())); + return Fixes; +} + } + return std::nullopt; // Not in the cases that we can handle for now, give up. +} std::optional UPCPreIncrementGadget::getFixits(const Strategy ) const { DeclUseList DREs = getClaimedVarUseSites(); diff --git a/clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-add-assign.cpp b/clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-add-assign.cpp new file mode 100644 index 000..e2b9a43dee9b3c3 --- /dev/null +++ b/clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-add-assign.cpp @@ -0,0 +1,38 @@ +// RUN: %clang_cc1 -std=c++20 -Wunsafe-buffer-usage \ +// RUN:
[clang] [-Wunsafe-buffer-usage] Add FixableGadget for AddAssign in UnspecifiedUntypedContext (PR #71862)
https://github.com/t-rasmud updated https://github.com/llvm/llvm-project/pull/71862 >From 6636745d1c444747a33c91b366a730d81ca5db5a Mon Sep 17 00:00:00 2001 From: Rashmi Mudduluru Date: Wed, 1 Nov 2023 13:43:12 -0700 Subject: [PATCH 01/11] [-Wunsafe-buffer-usage][WIP] Fixable gadget for AddAssign --- .../Analyses/UnsafeBufferUsageGadgets.def | 1 + clang/lib/Analysis/UnsafeBufferUsage.cpp | 65 +++ ...-unsafe-buffer-usage-fixits-add-assign.cpp | 38 +++ 3 files changed, 104 insertions(+) create mode 100644 clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-add-assign.cpp diff --git a/clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def b/clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def index ff687a0d178bdea..757ee452ced7488 100644 --- a/clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def +++ b/clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def @@ -36,6 +36,7 @@ FIXABLE_GADGET(PointerDereference) FIXABLE_GADGET(UPCAddressofArraySubscript) // '[any]' in an Unspecified Pointer Context FIXABLE_GADGET(UPCStandalonePointer) FIXABLE_GADGET(UPCPreIncrement)// '++Ptr' in an Unspecified Pointer Context +FIXABLE_GADGET(UUCAddAssign)// 'Ptr += n' in an Unspecified Untyped Context FIXABLE_GADGET(PointerAssignment) FIXABLE_GADGET(PointerInit) diff --git a/clang/lib/Analysis/UnsafeBufferUsage.cpp b/clang/lib/Analysis/UnsafeBufferUsage.cpp index e332a3609290aac..7b79f5360c79d6e 100644 --- a/clang/lib/Analysis/UnsafeBufferUsage.cpp +++ b/clang/lib/Analysis/UnsafeBufferUsage.cpp @@ -1028,6 +1028,42 @@ class UPCPreIncrementGadget : public FixableGadget { } }; +// Representing a pointer type expression of the form `Ptr += n` in an +// Unspecified Untyped Context (UUC): +class UUCAddAssignGadget : public FixableGadget { +private: + static constexpr const char *const UUCAddAssignTag = +"PointerAddAssignUnderUUC"; + const BinaryOperator *Node; // the `Ptr += n` node + +public: + UUCAddAssignGadget(const MatchFinder::MatchResult ) +: FixableGadget(Kind::UUCAddAssign), + Node(Result.Nodes.getNodeAs(UUCAddAssignTag)) { +assert(Node != nullptr && "Expecting a non-null matching result"); + } + + static bool classof(const Gadget *G) { +return G->getKind() == Kind::UUCAddAssign; + } + + static Matcher matcher() { +return stmt(isInUnspecifiedUntypedContext(expr(ignoringImpCasts( +binaryOperator(hasOperatorName("+="), + hasLHS(declRefExpr( +toSupportedVariable())) + ).bind(UUCAddAssignTag); + } + + virtual std::optional getFixits(const Strategy ) const override; + + virtual const Stmt *getBaseStmt() const override { return Node; } + + virtual DeclUseList getClaimedVarUseSites() const override { +return {dyn_cast(Node->getLHS())}; + } +}; + // Representing a fixable expression of the form `*(ptr + 123)` or `*(123 + // ptr)`: class DerefSimplePtrArithFixableGadget : public FixableGadget { @@ -1766,6 +1802,35 @@ fixUPCAddressofArraySubscriptWithSpan(const UnaryOperator *Node) { FixItHint::CreateReplacement(Node->getSourceRange(), SS.str())}; } +std::optional UUCAddAssignGadget::getFixits(const Strategy ) const { + DeclUseList DREs = getClaimedVarUseSites(); + + if (DREs.size() != 1) +return std::nullopt; // In cases of `Ptr += n` where `Ptr` is not a DRE, we + // give up + if (const VarDecl *VD = dyn_cast(DREs.front()->getDecl())) { +if (S.lookup(VD) == Strategy::Kind::Span) { + FixItList Fixes; + std::stringstream SS; + const Stmt *AddAssignNode = getBaseStmt(); + StringRef varName = VD->getName(); + const ASTContext = VD->getASTContext(); + + // To transform UUC(p += n) to UUC((p = p.subspan(1)).data()): + SS << varName.data() << " = " << varName.data() + << ".subspan(" << getUserFillPlaceHolder() << ")"; + std::optional AddAssignLocation = + getEndCharLoc(AddAssignNode, Ctx.getSourceManager(), Ctx.getLangOpts()); + if (!AddAssignLocation) +return std::nullopt; + + Fixes.push_back(FixItHint::CreateReplacement( + SourceRange(AddAssignNode->getBeginLoc(), *AddAssignLocation), SS.str())); + return Fixes; +} + } + return std::nullopt; // Not in the cases that we can handle for now, give up. +} std::optional UPCPreIncrementGadget::getFixits(const Strategy ) const { DeclUseList DREs = getClaimedVarUseSites(); diff --git a/clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-add-assign.cpp b/clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-add-assign.cpp new file mode 100644 index 000..e2b9a43dee9b3c3 --- /dev/null +++ b/clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-add-assign.cpp @@ -0,0 +1,38 @@ +// RUN: %clang_cc1 -std=c++20 -Wunsafe-buffer-usage \ +// RUN:
[clang] [-Wunsafe-buffer-usage] Add FixableGadget for AddAssign in UnspecifiedUntypedContext (PR #71862)
https://github.com/t-rasmud updated https://github.com/llvm/llvm-project/pull/71862 >From 6636745d1c444747a33c91b366a730d81ca5db5a Mon Sep 17 00:00:00 2001 From: Rashmi Mudduluru Date: Wed, 1 Nov 2023 13:43:12 -0700 Subject: [PATCH 01/10] [-Wunsafe-buffer-usage][WIP] Fixable gadget for AddAssign --- .../Analyses/UnsafeBufferUsageGadgets.def | 1 + clang/lib/Analysis/UnsafeBufferUsage.cpp | 65 +++ ...-unsafe-buffer-usage-fixits-add-assign.cpp | 38 +++ 3 files changed, 104 insertions(+) create mode 100644 clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-add-assign.cpp diff --git a/clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def b/clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def index ff687a0d178bdea..757ee452ced7488 100644 --- a/clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def +++ b/clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def @@ -36,6 +36,7 @@ FIXABLE_GADGET(PointerDereference) FIXABLE_GADGET(UPCAddressofArraySubscript) // '[any]' in an Unspecified Pointer Context FIXABLE_GADGET(UPCStandalonePointer) FIXABLE_GADGET(UPCPreIncrement)// '++Ptr' in an Unspecified Pointer Context +FIXABLE_GADGET(UUCAddAssign)// 'Ptr += n' in an Unspecified Untyped Context FIXABLE_GADGET(PointerAssignment) FIXABLE_GADGET(PointerInit) diff --git a/clang/lib/Analysis/UnsafeBufferUsage.cpp b/clang/lib/Analysis/UnsafeBufferUsage.cpp index e332a3609290aac..7b79f5360c79d6e 100644 --- a/clang/lib/Analysis/UnsafeBufferUsage.cpp +++ b/clang/lib/Analysis/UnsafeBufferUsage.cpp @@ -1028,6 +1028,42 @@ class UPCPreIncrementGadget : public FixableGadget { } }; +// Representing a pointer type expression of the form `Ptr += n` in an +// Unspecified Untyped Context (UUC): +class UUCAddAssignGadget : public FixableGadget { +private: + static constexpr const char *const UUCAddAssignTag = +"PointerAddAssignUnderUUC"; + const BinaryOperator *Node; // the `Ptr += n` node + +public: + UUCAddAssignGadget(const MatchFinder::MatchResult ) +: FixableGadget(Kind::UUCAddAssign), + Node(Result.Nodes.getNodeAs(UUCAddAssignTag)) { +assert(Node != nullptr && "Expecting a non-null matching result"); + } + + static bool classof(const Gadget *G) { +return G->getKind() == Kind::UUCAddAssign; + } + + static Matcher matcher() { +return stmt(isInUnspecifiedUntypedContext(expr(ignoringImpCasts( +binaryOperator(hasOperatorName("+="), + hasLHS(declRefExpr( +toSupportedVariable())) + ).bind(UUCAddAssignTag); + } + + virtual std::optional getFixits(const Strategy ) const override; + + virtual const Stmt *getBaseStmt() const override { return Node; } + + virtual DeclUseList getClaimedVarUseSites() const override { +return {dyn_cast(Node->getLHS())}; + } +}; + // Representing a fixable expression of the form `*(ptr + 123)` or `*(123 + // ptr)`: class DerefSimplePtrArithFixableGadget : public FixableGadget { @@ -1766,6 +1802,35 @@ fixUPCAddressofArraySubscriptWithSpan(const UnaryOperator *Node) { FixItHint::CreateReplacement(Node->getSourceRange(), SS.str())}; } +std::optional UUCAddAssignGadget::getFixits(const Strategy ) const { + DeclUseList DREs = getClaimedVarUseSites(); + + if (DREs.size() != 1) +return std::nullopt; // In cases of `Ptr += n` where `Ptr` is not a DRE, we + // give up + if (const VarDecl *VD = dyn_cast(DREs.front()->getDecl())) { +if (S.lookup(VD) == Strategy::Kind::Span) { + FixItList Fixes; + std::stringstream SS; + const Stmt *AddAssignNode = getBaseStmt(); + StringRef varName = VD->getName(); + const ASTContext = VD->getASTContext(); + + // To transform UUC(p += n) to UUC((p = p.subspan(1)).data()): + SS << varName.data() << " = " << varName.data() + << ".subspan(" << getUserFillPlaceHolder() << ")"; + std::optional AddAssignLocation = + getEndCharLoc(AddAssignNode, Ctx.getSourceManager(), Ctx.getLangOpts()); + if (!AddAssignLocation) +return std::nullopt; + + Fixes.push_back(FixItHint::CreateReplacement( + SourceRange(AddAssignNode->getBeginLoc(), *AddAssignLocation), SS.str())); + return Fixes; +} + } + return std::nullopt; // Not in the cases that we can handle for now, give up. +} std::optional UPCPreIncrementGadget::getFixits(const Strategy ) const { DeclUseList DREs = getClaimedVarUseSites(); diff --git a/clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-add-assign.cpp b/clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-add-assign.cpp new file mode 100644 index 000..e2b9a43dee9b3c3 --- /dev/null +++ b/clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-add-assign.cpp @@ -0,0 +1,38 @@ +// RUN: %clang_cc1 -std=c++20 -Wunsafe-buffer-usage \ +// RUN:
[clang] [-Wunsafe-buffer-usage] Add FixableGadget for AddAssign in UnspecifiedUntypedContext (PR #71862)
@@ -0,0 +1,55 @@ +// RUN: %clang_cc1 -std=c++20 -Wunsafe-buffer-usage \ +// RUN:-fsafe-buffer-usage-suggestions \ +// RUN:-fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s +void foo(int * , int *); + +void add_assign_test(unsigned int n, int *a, int y) { + int *p = new int[10]; + // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:11}:"std::span p" + // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:12-[[@LINE-2]]:12}:"{" + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:23-[[@LINE-3]]:23}:", 10}" + p += 2; + // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:9}:"p = p.subspan(2)" t-rasmud wrote: IIUC, the default for count is `std::dynamic_extent` which ensures the correct number of elements in the subspan (and I guess the fixit for UPC pre-increment makes this assumption as well.) Is this not the case? https://github.com/llvm/llvm-project/pull/71862 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [-Wunsafe-buffer-usage] Add FixableGadget for AddAssign in UnspecifiedUntypedContext (PR #71862)
https://github.com/t-rasmud updated https://github.com/llvm/llvm-project/pull/71862 >From 6636745d1c444747a33c91b366a730d81ca5db5a Mon Sep 17 00:00:00 2001 From: Rashmi Mudduluru Date: Wed, 1 Nov 2023 13:43:12 -0700 Subject: [PATCH 1/9] [-Wunsafe-buffer-usage][WIP] Fixable gadget for AddAssign --- .../Analyses/UnsafeBufferUsageGadgets.def | 1 + clang/lib/Analysis/UnsafeBufferUsage.cpp | 65 +++ ...-unsafe-buffer-usage-fixits-add-assign.cpp | 38 +++ 3 files changed, 104 insertions(+) create mode 100644 clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-add-assign.cpp diff --git a/clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def b/clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def index ff687a0d178bdea..757ee452ced7488 100644 --- a/clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def +++ b/clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def @@ -36,6 +36,7 @@ FIXABLE_GADGET(PointerDereference) FIXABLE_GADGET(UPCAddressofArraySubscript) // '[any]' in an Unspecified Pointer Context FIXABLE_GADGET(UPCStandalonePointer) FIXABLE_GADGET(UPCPreIncrement)// '++Ptr' in an Unspecified Pointer Context +FIXABLE_GADGET(UUCAddAssign)// 'Ptr += n' in an Unspecified Untyped Context FIXABLE_GADGET(PointerAssignment) FIXABLE_GADGET(PointerInit) diff --git a/clang/lib/Analysis/UnsafeBufferUsage.cpp b/clang/lib/Analysis/UnsafeBufferUsage.cpp index e332a3609290aac..7b79f5360c79d6e 100644 --- a/clang/lib/Analysis/UnsafeBufferUsage.cpp +++ b/clang/lib/Analysis/UnsafeBufferUsage.cpp @@ -1028,6 +1028,42 @@ class UPCPreIncrementGadget : public FixableGadget { } }; +// Representing a pointer type expression of the form `Ptr += n` in an +// Unspecified Untyped Context (UUC): +class UUCAddAssignGadget : public FixableGadget { +private: + static constexpr const char *const UUCAddAssignTag = +"PointerAddAssignUnderUUC"; + const BinaryOperator *Node; // the `Ptr += n` node + +public: + UUCAddAssignGadget(const MatchFinder::MatchResult ) +: FixableGadget(Kind::UUCAddAssign), + Node(Result.Nodes.getNodeAs(UUCAddAssignTag)) { +assert(Node != nullptr && "Expecting a non-null matching result"); + } + + static bool classof(const Gadget *G) { +return G->getKind() == Kind::UUCAddAssign; + } + + static Matcher matcher() { +return stmt(isInUnspecifiedUntypedContext(expr(ignoringImpCasts( +binaryOperator(hasOperatorName("+="), + hasLHS(declRefExpr( +toSupportedVariable())) + ).bind(UUCAddAssignTag); + } + + virtual std::optional getFixits(const Strategy ) const override; + + virtual const Stmt *getBaseStmt() const override { return Node; } + + virtual DeclUseList getClaimedVarUseSites() const override { +return {dyn_cast(Node->getLHS())}; + } +}; + // Representing a fixable expression of the form `*(ptr + 123)` or `*(123 + // ptr)`: class DerefSimplePtrArithFixableGadget : public FixableGadget { @@ -1766,6 +1802,35 @@ fixUPCAddressofArraySubscriptWithSpan(const UnaryOperator *Node) { FixItHint::CreateReplacement(Node->getSourceRange(), SS.str())}; } +std::optional UUCAddAssignGadget::getFixits(const Strategy ) const { + DeclUseList DREs = getClaimedVarUseSites(); + + if (DREs.size() != 1) +return std::nullopt; // In cases of `Ptr += n` where `Ptr` is not a DRE, we + // give up + if (const VarDecl *VD = dyn_cast(DREs.front()->getDecl())) { +if (S.lookup(VD) == Strategy::Kind::Span) { + FixItList Fixes; + std::stringstream SS; + const Stmt *AddAssignNode = getBaseStmt(); + StringRef varName = VD->getName(); + const ASTContext = VD->getASTContext(); + + // To transform UUC(p += n) to UUC((p = p.subspan(1)).data()): + SS << varName.data() << " = " << varName.data() + << ".subspan(" << getUserFillPlaceHolder() << ")"; + std::optional AddAssignLocation = + getEndCharLoc(AddAssignNode, Ctx.getSourceManager(), Ctx.getLangOpts()); + if (!AddAssignLocation) +return std::nullopt; + + Fixes.push_back(FixItHint::CreateReplacement( + SourceRange(AddAssignNode->getBeginLoc(), *AddAssignLocation), SS.str())); + return Fixes; +} + } + return std::nullopt; // Not in the cases that we can handle for now, give up. +} std::optional UPCPreIncrementGadget::getFixits(const Strategy ) const { DeclUseList DREs = getClaimedVarUseSites(); diff --git a/clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-add-assign.cpp b/clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-add-assign.cpp new file mode 100644 index 000..e2b9a43dee9b3c3 --- /dev/null +++ b/clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-add-assign.cpp @@ -0,0 +1,38 @@ +// RUN: %clang_cc1 -std=c++20 -Wunsafe-buffer-usage \ +// RUN:
[clang] [-Wunsafe-buffer-usage] Add FixableGadget for AddAssign in UnspecifiedUntypedContext (PR #71862)
https://github.com/t-rasmud updated https://github.com/llvm/llvm-project/pull/71862 >From 6636745d1c444747a33c91b366a730d81ca5db5a Mon Sep 17 00:00:00 2001 From: Rashmi Mudduluru Date: Wed, 1 Nov 2023 13:43:12 -0700 Subject: [PATCH 1/8] [-Wunsafe-buffer-usage][WIP] Fixable gadget for AddAssign --- .../Analyses/UnsafeBufferUsageGadgets.def | 1 + clang/lib/Analysis/UnsafeBufferUsage.cpp | 65 +++ ...-unsafe-buffer-usage-fixits-add-assign.cpp | 38 +++ 3 files changed, 104 insertions(+) create mode 100644 clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-add-assign.cpp diff --git a/clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def b/clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def index ff687a0d178bdea..757ee452ced7488 100644 --- a/clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def +++ b/clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def @@ -36,6 +36,7 @@ FIXABLE_GADGET(PointerDereference) FIXABLE_GADGET(UPCAddressofArraySubscript) // '[any]' in an Unspecified Pointer Context FIXABLE_GADGET(UPCStandalonePointer) FIXABLE_GADGET(UPCPreIncrement)// '++Ptr' in an Unspecified Pointer Context +FIXABLE_GADGET(UUCAddAssign)// 'Ptr += n' in an Unspecified Untyped Context FIXABLE_GADGET(PointerAssignment) FIXABLE_GADGET(PointerInit) diff --git a/clang/lib/Analysis/UnsafeBufferUsage.cpp b/clang/lib/Analysis/UnsafeBufferUsage.cpp index e332a3609290aac..7b79f5360c79d6e 100644 --- a/clang/lib/Analysis/UnsafeBufferUsage.cpp +++ b/clang/lib/Analysis/UnsafeBufferUsage.cpp @@ -1028,6 +1028,42 @@ class UPCPreIncrementGadget : public FixableGadget { } }; +// Representing a pointer type expression of the form `Ptr += n` in an +// Unspecified Untyped Context (UUC): +class UUCAddAssignGadget : public FixableGadget { +private: + static constexpr const char *const UUCAddAssignTag = +"PointerAddAssignUnderUUC"; + const BinaryOperator *Node; // the `Ptr += n` node + +public: + UUCAddAssignGadget(const MatchFinder::MatchResult ) +: FixableGadget(Kind::UUCAddAssign), + Node(Result.Nodes.getNodeAs(UUCAddAssignTag)) { +assert(Node != nullptr && "Expecting a non-null matching result"); + } + + static bool classof(const Gadget *G) { +return G->getKind() == Kind::UUCAddAssign; + } + + static Matcher matcher() { +return stmt(isInUnspecifiedUntypedContext(expr(ignoringImpCasts( +binaryOperator(hasOperatorName("+="), + hasLHS(declRefExpr( +toSupportedVariable())) + ).bind(UUCAddAssignTag); + } + + virtual std::optional getFixits(const Strategy ) const override; + + virtual const Stmt *getBaseStmt() const override { return Node; } + + virtual DeclUseList getClaimedVarUseSites() const override { +return {dyn_cast(Node->getLHS())}; + } +}; + // Representing a fixable expression of the form `*(ptr + 123)` or `*(123 + // ptr)`: class DerefSimplePtrArithFixableGadget : public FixableGadget { @@ -1766,6 +1802,35 @@ fixUPCAddressofArraySubscriptWithSpan(const UnaryOperator *Node) { FixItHint::CreateReplacement(Node->getSourceRange(), SS.str())}; } +std::optional UUCAddAssignGadget::getFixits(const Strategy ) const { + DeclUseList DREs = getClaimedVarUseSites(); + + if (DREs.size() != 1) +return std::nullopt; // In cases of `Ptr += n` where `Ptr` is not a DRE, we + // give up + if (const VarDecl *VD = dyn_cast(DREs.front()->getDecl())) { +if (S.lookup(VD) == Strategy::Kind::Span) { + FixItList Fixes; + std::stringstream SS; + const Stmt *AddAssignNode = getBaseStmt(); + StringRef varName = VD->getName(); + const ASTContext = VD->getASTContext(); + + // To transform UUC(p += n) to UUC((p = p.subspan(1)).data()): + SS << varName.data() << " = " << varName.data() + << ".subspan(" << getUserFillPlaceHolder() << ")"; + std::optional AddAssignLocation = + getEndCharLoc(AddAssignNode, Ctx.getSourceManager(), Ctx.getLangOpts()); + if (!AddAssignLocation) +return std::nullopt; + + Fixes.push_back(FixItHint::CreateReplacement( + SourceRange(AddAssignNode->getBeginLoc(), *AddAssignLocation), SS.str())); + return Fixes; +} + } + return std::nullopt; // Not in the cases that we can handle for now, give up. +} std::optional UPCPreIncrementGadget::getFixits(const Strategy ) const { DeclUseList DREs = getClaimedVarUseSites(); diff --git a/clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-add-assign.cpp b/clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-add-assign.cpp new file mode 100644 index 000..e2b9a43dee9b3c3 --- /dev/null +++ b/clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-add-assign.cpp @@ -0,0 +1,38 @@ +// RUN: %clang_cc1 -std=c++20 -Wunsafe-buffer-usage \ +// RUN:
[clang] [-Wunsafe-buffer-usage] Add FixableGadget for AddAssign in UnspecifiedUntypedContext (PR #71862)
https://github.com/t-rasmud updated https://github.com/llvm/llvm-project/pull/71862 >From 6636745d1c444747a33c91b366a730d81ca5db5a Mon Sep 17 00:00:00 2001 From: Rashmi Mudduluru Date: Wed, 1 Nov 2023 13:43:12 -0700 Subject: [PATCH 1/7] [-Wunsafe-buffer-usage][WIP] Fixable gadget for AddAssign --- .../Analyses/UnsafeBufferUsageGadgets.def | 1 + clang/lib/Analysis/UnsafeBufferUsage.cpp | 65 +++ ...-unsafe-buffer-usage-fixits-add-assign.cpp | 38 +++ 3 files changed, 104 insertions(+) create mode 100644 clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-add-assign.cpp diff --git a/clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def b/clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def index ff687a0d178bdea..757ee452ced7488 100644 --- a/clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def +++ b/clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def @@ -36,6 +36,7 @@ FIXABLE_GADGET(PointerDereference) FIXABLE_GADGET(UPCAddressofArraySubscript) // '[any]' in an Unspecified Pointer Context FIXABLE_GADGET(UPCStandalonePointer) FIXABLE_GADGET(UPCPreIncrement)// '++Ptr' in an Unspecified Pointer Context +FIXABLE_GADGET(UUCAddAssign)// 'Ptr += n' in an Unspecified Untyped Context FIXABLE_GADGET(PointerAssignment) FIXABLE_GADGET(PointerInit) diff --git a/clang/lib/Analysis/UnsafeBufferUsage.cpp b/clang/lib/Analysis/UnsafeBufferUsage.cpp index e332a3609290aac..7b79f5360c79d6e 100644 --- a/clang/lib/Analysis/UnsafeBufferUsage.cpp +++ b/clang/lib/Analysis/UnsafeBufferUsage.cpp @@ -1028,6 +1028,42 @@ class UPCPreIncrementGadget : public FixableGadget { } }; +// Representing a pointer type expression of the form `Ptr += n` in an +// Unspecified Untyped Context (UUC): +class UUCAddAssignGadget : public FixableGadget { +private: + static constexpr const char *const UUCAddAssignTag = +"PointerAddAssignUnderUUC"; + const BinaryOperator *Node; // the `Ptr += n` node + +public: + UUCAddAssignGadget(const MatchFinder::MatchResult ) +: FixableGadget(Kind::UUCAddAssign), + Node(Result.Nodes.getNodeAs(UUCAddAssignTag)) { +assert(Node != nullptr && "Expecting a non-null matching result"); + } + + static bool classof(const Gadget *G) { +return G->getKind() == Kind::UUCAddAssign; + } + + static Matcher matcher() { +return stmt(isInUnspecifiedUntypedContext(expr(ignoringImpCasts( +binaryOperator(hasOperatorName("+="), + hasLHS(declRefExpr( +toSupportedVariable())) + ).bind(UUCAddAssignTag); + } + + virtual std::optional getFixits(const Strategy ) const override; + + virtual const Stmt *getBaseStmt() const override { return Node; } + + virtual DeclUseList getClaimedVarUseSites() const override { +return {dyn_cast(Node->getLHS())}; + } +}; + // Representing a fixable expression of the form `*(ptr + 123)` or `*(123 + // ptr)`: class DerefSimplePtrArithFixableGadget : public FixableGadget { @@ -1766,6 +1802,35 @@ fixUPCAddressofArraySubscriptWithSpan(const UnaryOperator *Node) { FixItHint::CreateReplacement(Node->getSourceRange(), SS.str())}; } +std::optional UUCAddAssignGadget::getFixits(const Strategy ) const { + DeclUseList DREs = getClaimedVarUseSites(); + + if (DREs.size() != 1) +return std::nullopt; // In cases of `Ptr += n` where `Ptr` is not a DRE, we + // give up + if (const VarDecl *VD = dyn_cast(DREs.front()->getDecl())) { +if (S.lookup(VD) == Strategy::Kind::Span) { + FixItList Fixes; + std::stringstream SS; + const Stmt *AddAssignNode = getBaseStmt(); + StringRef varName = VD->getName(); + const ASTContext = VD->getASTContext(); + + // To transform UUC(p += n) to UUC((p = p.subspan(1)).data()): + SS << varName.data() << " = " << varName.data() + << ".subspan(" << getUserFillPlaceHolder() << ")"; + std::optional AddAssignLocation = + getEndCharLoc(AddAssignNode, Ctx.getSourceManager(), Ctx.getLangOpts()); + if (!AddAssignLocation) +return std::nullopt; + + Fixes.push_back(FixItHint::CreateReplacement( + SourceRange(AddAssignNode->getBeginLoc(), *AddAssignLocation), SS.str())); + return Fixes; +} + } + return std::nullopt; // Not in the cases that we can handle for now, give up. +} std::optional UPCPreIncrementGadget::getFixits(const Strategy ) const { DeclUseList DREs = getClaimedVarUseSites(); diff --git a/clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-add-assign.cpp b/clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-add-assign.cpp new file mode 100644 index 000..e2b9a43dee9b3c3 --- /dev/null +++ b/clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-add-assign.cpp @@ -0,0 +1,38 @@ +// RUN: %clang_cc1 -std=c++20 -Wunsafe-buffer-usage \ +// RUN:
[clang] [-Wunsafe-buffer-usage] Add FixableGadget for AddAssign in UnspecifiedUntypedContext (PR #71862)
@@ -1028,6 +1028,50 @@ class UPCPreIncrementGadget : public FixableGadget { } }; +// Representing a pointer type expression of the form `Ptr += n` in an +// Unspecified Untyped Context (UUC): +class UUCAddAssignGadget : public FixableGadget { +private: + static constexpr const char *const UUCAddAssignTag = + "PointerAddAssignUnderUUC"; + static constexpr const char *const IntOffsetTag = "IntOffset"; + static constexpr const char *const OffsetTag = "Offset"; + + const BinaryOperator *Node; // the `Ptr += n` node + const IntegerLiteral *IntOffset = nullptr; + const DeclRefExpr *Offset = nullptr; + +public: + UUCAddAssignGadget(const MatchFinder::MatchResult ) + : FixableGadget(Kind::UUCAddAssign), +Node(Result.Nodes.getNodeAs(UUCAddAssignTag)), +IntOffset(Result.Nodes.getNodeAs(IntOffsetTag)), +Offset(Result.Nodes.getNodeAs(OffsetTag)) { +assert(Node != nullptr && "Expecting a non-null matching result"); + } + + static bool classof(const Gadget *G) { +return G->getKind() == Kind::UUCAddAssign; + } + + static Matcher matcher() { +return stmt(isInUnspecifiedUntypedContext(expr(ignoringImpCasts( +binaryOperator( +hasOperatorName("+="), hasLHS(declRefExpr(toSupportedVariable())), +hasRHS(expr(anyOf(ignoringImpCasts(declRefExpr().bind(OffsetTag)), + integerLiteral().bind(IntOffsetTag) t-rasmud wrote: I make this differentiation to ensure we do not suggest a fixit if the integer literal happens to be negative. Although there's no such check in the case of a `DeclRefExpr`. https://github.com/llvm/llvm-project/pull/71862 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [-Wunsafe-buffer-usage] Add FixableGadget for AddAssign in UnspecifiedUntypedContext (PR #71862)
https://github.com/t-rasmud updated https://github.com/llvm/llvm-project/pull/71862 >From 6636745d1c444747a33c91b366a730d81ca5db5a Mon Sep 17 00:00:00 2001 From: Rashmi Mudduluru Date: Wed, 1 Nov 2023 13:43:12 -0700 Subject: [PATCH 1/6] [-Wunsafe-buffer-usage][WIP] Fixable gadget for AddAssign --- .../Analyses/UnsafeBufferUsageGadgets.def | 1 + clang/lib/Analysis/UnsafeBufferUsage.cpp | 65 +++ ...-unsafe-buffer-usage-fixits-add-assign.cpp | 38 +++ 3 files changed, 104 insertions(+) create mode 100644 clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-add-assign.cpp diff --git a/clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def b/clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def index ff687a0d178bdea..757ee452ced7488 100644 --- a/clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def +++ b/clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def @@ -36,6 +36,7 @@ FIXABLE_GADGET(PointerDereference) FIXABLE_GADGET(UPCAddressofArraySubscript) // '[any]' in an Unspecified Pointer Context FIXABLE_GADGET(UPCStandalonePointer) FIXABLE_GADGET(UPCPreIncrement)// '++Ptr' in an Unspecified Pointer Context +FIXABLE_GADGET(UUCAddAssign)// 'Ptr += n' in an Unspecified Untyped Context FIXABLE_GADGET(PointerAssignment) FIXABLE_GADGET(PointerInit) diff --git a/clang/lib/Analysis/UnsafeBufferUsage.cpp b/clang/lib/Analysis/UnsafeBufferUsage.cpp index e332a3609290aac..7b79f5360c79d6e 100644 --- a/clang/lib/Analysis/UnsafeBufferUsage.cpp +++ b/clang/lib/Analysis/UnsafeBufferUsage.cpp @@ -1028,6 +1028,42 @@ class UPCPreIncrementGadget : public FixableGadget { } }; +// Representing a pointer type expression of the form `Ptr += n` in an +// Unspecified Untyped Context (UUC): +class UUCAddAssignGadget : public FixableGadget { +private: + static constexpr const char *const UUCAddAssignTag = +"PointerAddAssignUnderUUC"; + const BinaryOperator *Node; // the `Ptr += n` node + +public: + UUCAddAssignGadget(const MatchFinder::MatchResult ) +: FixableGadget(Kind::UUCAddAssign), + Node(Result.Nodes.getNodeAs(UUCAddAssignTag)) { +assert(Node != nullptr && "Expecting a non-null matching result"); + } + + static bool classof(const Gadget *G) { +return G->getKind() == Kind::UUCAddAssign; + } + + static Matcher matcher() { +return stmt(isInUnspecifiedUntypedContext(expr(ignoringImpCasts( +binaryOperator(hasOperatorName("+="), + hasLHS(declRefExpr( +toSupportedVariable())) + ).bind(UUCAddAssignTag); + } + + virtual std::optional getFixits(const Strategy ) const override; + + virtual const Stmt *getBaseStmt() const override { return Node; } + + virtual DeclUseList getClaimedVarUseSites() const override { +return {dyn_cast(Node->getLHS())}; + } +}; + // Representing a fixable expression of the form `*(ptr + 123)` or `*(123 + // ptr)`: class DerefSimplePtrArithFixableGadget : public FixableGadget { @@ -1766,6 +1802,35 @@ fixUPCAddressofArraySubscriptWithSpan(const UnaryOperator *Node) { FixItHint::CreateReplacement(Node->getSourceRange(), SS.str())}; } +std::optional UUCAddAssignGadget::getFixits(const Strategy ) const { + DeclUseList DREs = getClaimedVarUseSites(); + + if (DREs.size() != 1) +return std::nullopt; // In cases of `Ptr += n` where `Ptr` is not a DRE, we + // give up + if (const VarDecl *VD = dyn_cast(DREs.front()->getDecl())) { +if (S.lookup(VD) == Strategy::Kind::Span) { + FixItList Fixes; + std::stringstream SS; + const Stmt *AddAssignNode = getBaseStmt(); + StringRef varName = VD->getName(); + const ASTContext = VD->getASTContext(); + + // To transform UUC(p += n) to UUC((p = p.subspan(1)).data()): + SS << varName.data() << " = " << varName.data() + << ".subspan(" << getUserFillPlaceHolder() << ")"; + std::optional AddAssignLocation = + getEndCharLoc(AddAssignNode, Ctx.getSourceManager(), Ctx.getLangOpts()); + if (!AddAssignLocation) +return std::nullopt; + + Fixes.push_back(FixItHint::CreateReplacement( + SourceRange(AddAssignNode->getBeginLoc(), *AddAssignLocation), SS.str())); + return Fixes; +} + } + return std::nullopt; // Not in the cases that we can handle for now, give up. +} std::optional UPCPreIncrementGadget::getFixits(const Strategy ) const { DeclUseList DREs = getClaimedVarUseSites(); diff --git a/clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-add-assign.cpp b/clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-add-assign.cpp new file mode 100644 index 000..e2b9a43dee9b3c3 --- /dev/null +++ b/clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-add-assign.cpp @@ -0,0 +1,38 @@ +// RUN: %clang_cc1 -std=c++20 -Wunsafe-buffer-usage \ +// RUN:
[clang] [-Wunsafe-buffer-usage] Add FixableGadget for AddAssign in UnspecifiedUntypedContext (PR #71862)
https://github.com/t-rasmud updated https://github.com/llvm/llvm-project/pull/71862 >From 6636745d1c444747a33c91b366a730d81ca5db5a Mon Sep 17 00:00:00 2001 From: Rashmi Mudduluru Date: Wed, 1 Nov 2023 13:43:12 -0700 Subject: [PATCH 1/5] [-Wunsafe-buffer-usage][WIP] Fixable gadget for AddAssign --- .../Analyses/UnsafeBufferUsageGadgets.def | 1 + clang/lib/Analysis/UnsafeBufferUsage.cpp | 65 +++ ...-unsafe-buffer-usage-fixits-add-assign.cpp | 38 +++ 3 files changed, 104 insertions(+) create mode 100644 clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-add-assign.cpp diff --git a/clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def b/clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def index ff687a0d178bdea..757ee452ced7488 100644 --- a/clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def +++ b/clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def @@ -36,6 +36,7 @@ FIXABLE_GADGET(PointerDereference) FIXABLE_GADGET(UPCAddressofArraySubscript) // '[any]' in an Unspecified Pointer Context FIXABLE_GADGET(UPCStandalonePointer) FIXABLE_GADGET(UPCPreIncrement)// '++Ptr' in an Unspecified Pointer Context +FIXABLE_GADGET(UUCAddAssign)// 'Ptr += n' in an Unspecified Untyped Context FIXABLE_GADGET(PointerAssignment) FIXABLE_GADGET(PointerInit) diff --git a/clang/lib/Analysis/UnsafeBufferUsage.cpp b/clang/lib/Analysis/UnsafeBufferUsage.cpp index e332a3609290aac..7b79f5360c79d6e 100644 --- a/clang/lib/Analysis/UnsafeBufferUsage.cpp +++ b/clang/lib/Analysis/UnsafeBufferUsage.cpp @@ -1028,6 +1028,42 @@ class UPCPreIncrementGadget : public FixableGadget { } }; +// Representing a pointer type expression of the form `Ptr += n` in an +// Unspecified Untyped Context (UUC): +class UUCAddAssignGadget : public FixableGadget { +private: + static constexpr const char *const UUCAddAssignTag = +"PointerAddAssignUnderUUC"; + const BinaryOperator *Node; // the `Ptr += n` node + +public: + UUCAddAssignGadget(const MatchFinder::MatchResult ) +: FixableGadget(Kind::UUCAddAssign), + Node(Result.Nodes.getNodeAs(UUCAddAssignTag)) { +assert(Node != nullptr && "Expecting a non-null matching result"); + } + + static bool classof(const Gadget *G) { +return G->getKind() == Kind::UUCAddAssign; + } + + static Matcher matcher() { +return stmt(isInUnspecifiedUntypedContext(expr(ignoringImpCasts( +binaryOperator(hasOperatorName("+="), + hasLHS(declRefExpr( +toSupportedVariable())) + ).bind(UUCAddAssignTag); + } + + virtual std::optional getFixits(const Strategy ) const override; + + virtual const Stmt *getBaseStmt() const override { return Node; } + + virtual DeclUseList getClaimedVarUseSites() const override { +return {dyn_cast(Node->getLHS())}; + } +}; + // Representing a fixable expression of the form `*(ptr + 123)` or `*(123 + // ptr)`: class DerefSimplePtrArithFixableGadget : public FixableGadget { @@ -1766,6 +1802,35 @@ fixUPCAddressofArraySubscriptWithSpan(const UnaryOperator *Node) { FixItHint::CreateReplacement(Node->getSourceRange(), SS.str())}; } +std::optional UUCAddAssignGadget::getFixits(const Strategy ) const { + DeclUseList DREs = getClaimedVarUseSites(); + + if (DREs.size() != 1) +return std::nullopt; // In cases of `Ptr += n` where `Ptr` is not a DRE, we + // give up + if (const VarDecl *VD = dyn_cast(DREs.front()->getDecl())) { +if (S.lookup(VD) == Strategy::Kind::Span) { + FixItList Fixes; + std::stringstream SS; + const Stmt *AddAssignNode = getBaseStmt(); + StringRef varName = VD->getName(); + const ASTContext = VD->getASTContext(); + + // To transform UUC(p += n) to UUC((p = p.subspan(1)).data()): + SS << varName.data() << " = " << varName.data() + << ".subspan(" << getUserFillPlaceHolder() << ")"; + std::optional AddAssignLocation = + getEndCharLoc(AddAssignNode, Ctx.getSourceManager(), Ctx.getLangOpts()); + if (!AddAssignLocation) +return std::nullopt; + + Fixes.push_back(FixItHint::CreateReplacement( + SourceRange(AddAssignNode->getBeginLoc(), *AddAssignLocation), SS.str())); + return Fixes; +} + } + return std::nullopt; // Not in the cases that we can handle for now, give up. +} std::optional UPCPreIncrementGadget::getFixits(const Strategy ) const { DeclUseList DREs = getClaimedVarUseSites(); diff --git a/clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-add-assign.cpp b/clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-add-assign.cpp new file mode 100644 index 000..e2b9a43dee9b3c3 --- /dev/null +++ b/clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-add-assign.cpp @@ -0,0 +1,38 @@ +// RUN: %clang_cc1 -std=c++20 -Wunsafe-buffer-usage \ +// RUN:
[clang] [-Wunsafe-buffer-usage] Add FixableGadget for AddAssign in UnspecifiedUntypedContext (PR #71862)
https://github.com/t-rasmud updated https://github.com/llvm/llvm-project/pull/71862 >From 6636745d1c444747a33c91b366a730d81ca5db5a Mon Sep 17 00:00:00 2001 From: Rashmi Mudduluru Date: Wed, 1 Nov 2023 13:43:12 -0700 Subject: [PATCH 1/4] [-Wunsafe-buffer-usage][WIP] Fixable gadget for AddAssign --- .../Analyses/UnsafeBufferUsageGadgets.def | 1 + clang/lib/Analysis/UnsafeBufferUsage.cpp | 65 +++ ...-unsafe-buffer-usage-fixits-add-assign.cpp | 38 +++ 3 files changed, 104 insertions(+) create mode 100644 clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-add-assign.cpp diff --git a/clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def b/clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def index ff687a0d178bdea..757ee452ced7488 100644 --- a/clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def +++ b/clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def @@ -36,6 +36,7 @@ FIXABLE_GADGET(PointerDereference) FIXABLE_GADGET(UPCAddressofArraySubscript) // '[any]' in an Unspecified Pointer Context FIXABLE_GADGET(UPCStandalonePointer) FIXABLE_GADGET(UPCPreIncrement)// '++Ptr' in an Unspecified Pointer Context +FIXABLE_GADGET(UUCAddAssign)// 'Ptr += n' in an Unspecified Untyped Context FIXABLE_GADGET(PointerAssignment) FIXABLE_GADGET(PointerInit) diff --git a/clang/lib/Analysis/UnsafeBufferUsage.cpp b/clang/lib/Analysis/UnsafeBufferUsage.cpp index e332a3609290aac..7b79f5360c79d6e 100644 --- a/clang/lib/Analysis/UnsafeBufferUsage.cpp +++ b/clang/lib/Analysis/UnsafeBufferUsage.cpp @@ -1028,6 +1028,42 @@ class UPCPreIncrementGadget : public FixableGadget { } }; +// Representing a pointer type expression of the form `Ptr += n` in an +// Unspecified Untyped Context (UUC): +class UUCAddAssignGadget : public FixableGadget { +private: + static constexpr const char *const UUCAddAssignTag = +"PointerAddAssignUnderUUC"; + const BinaryOperator *Node; // the `Ptr += n` node + +public: + UUCAddAssignGadget(const MatchFinder::MatchResult ) +: FixableGadget(Kind::UUCAddAssign), + Node(Result.Nodes.getNodeAs(UUCAddAssignTag)) { +assert(Node != nullptr && "Expecting a non-null matching result"); + } + + static bool classof(const Gadget *G) { +return G->getKind() == Kind::UUCAddAssign; + } + + static Matcher matcher() { +return stmt(isInUnspecifiedUntypedContext(expr(ignoringImpCasts( +binaryOperator(hasOperatorName("+="), + hasLHS(declRefExpr( +toSupportedVariable())) + ).bind(UUCAddAssignTag); + } + + virtual std::optional getFixits(const Strategy ) const override; + + virtual const Stmt *getBaseStmt() const override { return Node; } + + virtual DeclUseList getClaimedVarUseSites() const override { +return {dyn_cast(Node->getLHS())}; + } +}; + // Representing a fixable expression of the form `*(ptr + 123)` or `*(123 + // ptr)`: class DerefSimplePtrArithFixableGadget : public FixableGadget { @@ -1766,6 +1802,35 @@ fixUPCAddressofArraySubscriptWithSpan(const UnaryOperator *Node) { FixItHint::CreateReplacement(Node->getSourceRange(), SS.str())}; } +std::optional UUCAddAssignGadget::getFixits(const Strategy ) const { + DeclUseList DREs = getClaimedVarUseSites(); + + if (DREs.size() != 1) +return std::nullopt; // In cases of `Ptr += n` where `Ptr` is not a DRE, we + // give up + if (const VarDecl *VD = dyn_cast(DREs.front()->getDecl())) { +if (S.lookup(VD) == Strategy::Kind::Span) { + FixItList Fixes; + std::stringstream SS; + const Stmt *AddAssignNode = getBaseStmt(); + StringRef varName = VD->getName(); + const ASTContext = VD->getASTContext(); + + // To transform UUC(p += n) to UUC((p = p.subspan(1)).data()): + SS << varName.data() << " = " << varName.data() + << ".subspan(" << getUserFillPlaceHolder() << ")"; + std::optional AddAssignLocation = + getEndCharLoc(AddAssignNode, Ctx.getSourceManager(), Ctx.getLangOpts()); + if (!AddAssignLocation) +return std::nullopt; + + Fixes.push_back(FixItHint::CreateReplacement( + SourceRange(AddAssignNode->getBeginLoc(), *AddAssignLocation), SS.str())); + return Fixes; +} + } + return std::nullopt; // Not in the cases that we can handle for now, give up. +} std::optional UPCPreIncrementGadget::getFixits(const Strategy ) const { DeclUseList DREs = getClaimedVarUseSites(); diff --git a/clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-add-assign.cpp b/clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-add-assign.cpp new file mode 100644 index 000..e2b9a43dee9b3c3 --- /dev/null +++ b/clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-add-assign.cpp @@ -0,0 +1,38 @@ +// RUN: %clang_cc1 -std=c++20 -Wunsafe-buffer-usage \ +// RUN:
[clang] [-Wunsafe-buffer-usage] Add FixableGadget for AddAssign in UnspecifiedUntypedContext (PR #71862)
https://github.com/t-rasmud edited https://github.com/llvm/llvm-project/pull/71862 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] Add FixableGadget for AddAssign in UnspecifiedUntypedContext (PR #71862)
https://github.com/t-rasmud created https://github.com/llvm/llvm-project/pull/71862 None >From 6636745d1c444747a33c91b366a730d81ca5db5a Mon Sep 17 00:00:00 2001 From: Rashmi Mudduluru Date: Wed, 1 Nov 2023 13:43:12 -0700 Subject: [PATCH 1/3] [-Wunsafe-buffer-usage][WIP] Fixable gadget for AddAssign --- .../Analyses/UnsafeBufferUsageGadgets.def | 1 + clang/lib/Analysis/UnsafeBufferUsage.cpp | 65 +++ ...-unsafe-buffer-usage-fixits-add-assign.cpp | 38 +++ 3 files changed, 104 insertions(+) create mode 100644 clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-add-assign.cpp diff --git a/clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def b/clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def index ff687a0d178bdea..757ee452ced7488 100644 --- a/clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def +++ b/clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def @@ -36,6 +36,7 @@ FIXABLE_GADGET(PointerDereference) FIXABLE_GADGET(UPCAddressofArraySubscript) // '[any]' in an Unspecified Pointer Context FIXABLE_GADGET(UPCStandalonePointer) FIXABLE_GADGET(UPCPreIncrement)// '++Ptr' in an Unspecified Pointer Context +FIXABLE_GADGET(UUCAddAssign)// 'Ptr += n' in an Unspecified Untyped Context FIXABLE_GADGET(PointerAssignment) FIXABLE_GADGET(PointerInit) diff --git a/clang/lib/Analysis/UnsafeBufferUsage.cpp b/clang/lib/Analysis/UnsafeBufferUsage.cpp index e332a3609290aac..7b79f5360c79d6e 100644 --- a/clang/lib/Analysis/UnsafeBufferUsage.cpp +++ b/clang/lib/Analysis/UnsafeBufferUsage.cpp @@ -1028,6 +1028,42 @@ class UPCPreIncrementGadget : public FixableGadget { } }; +// Representing a pointer type expression of the form `Ptr += n` in an +// Unspecified Untyped Context (UUC): +class UUCAddAssignGadget : public FixableGadget { +private: + static constexpr const char *const UUCAddAssignTag = +"PointerAddAssignUnderUUC"; + const BinaryOperator *Node; // the `Ptr += n` node + +public: + UUCAddAssignGadget(const MatchFinder::MatchResult ) +: FixableGadget(Kind::UUCAddAssign), + Node(Result.Nodes.getNodeAs(UUCAddAssignTag)) { +assert(Node != nullptr && "Expecting a non-null matching result"); + } + + static bool classof(const Gadget *G) { +return G->getKind() == Kind::UUCAddAssign; + } + + static Matcher matcher() { +return stmt(isInUnspecifiedUntypedContext(expr(ignoringImpCasts( +binaryOperator(hasOperatorName("+="), + hasLHS(declRefExpr( +toSupportedVariable())) + ).bind(UUCAddAssignTag); + } + + virtual std::optional getFixits(const Strategy ) const override; + + virtual const Stmt *getBaseStmt() const override { return Node; } + + virtual DeclUseList getClaimedVarUseSites() const override { +return {dyn_cast(Node->getLHS())}; + } +}; + // Representing a fixable expression of the form `*(ptr + 123)` or `*(123 + // ptr)`: class DerefSimplePtrArithFixableGadget : public FixableGadget { @@ -1766,6 +1802,35 @@ fixUPCAddressofArraySubscriptWithSpan(const UnaryOperator *Node) { FixItHint::CreateReplacement(Node->getSourceRange(), SS.str())}; } +std::optional UUCAddAssignGadget::getFixits(const Strategy ) const { + DeclUseList DREs = getClaimedVarUseSites(); + + if (DREs.size() != 1) +return std::nullopt; // In cases of `Ptr += n` where `Ptr` is not a DRE, we + // give up + if (const VarDecl *VD = dyn_cast(DREs.front()->getDecl())) { +if (S.lookup(VD) == Strategy::Kind::Span) { + FixItList Fixes; + std::stringstream SS; + const Stmt *AddAssignNode = getBaseStmt(); + StringRef varName = VD->getName(); + const ASTContext = VD->getASTContext(); + + // To transform UUC(p += n) to UUC((p = p.subspan(1)).data()): + SS << varName.data() << " = " << varName.data() + << ".subspan(" << getUserFillPlaceHolder() << ")"; + std::optional AddAssignLocation = + getEndCharLoc(AddAssignNode, Ctx.getSourceManager(), Ctx.getLangOpts()); + if (!AddAssignLocation) +return std::nullopt; + + Fixes.push_back(FixItHint::CreateReplacement( + SourceRange(AddAssignNode->getBeginLoc(), *AddAssignLocation), SS.str())); + return Fixes; +} + } + return std::nullopt; // Not in the cases that we can handle for now, give up. +} std::optional UPCPreIncrementGadget::getFixits(const Strategy ) const { DeclUseList DREs = getClaimedVarUseSites(); diff --git a/clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-add-assign.cpp b/clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-add-assign.cpp new file mode 100644 index 000..e2b9a43dee9b3c3 --- /dev/null +++ b/clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-add-assign.cpp @@ -0,0 +1,38 @@ +// RUN: %clang_cc1 -std=c++20 -Wunsafe-buffer-usage \ +// RUN:
[clang] 87b8c85 - [-Wunsafe-bugger-usage] Clean tests: remove nondeterministic ordering
Author: Rashmi Mudduluru Date: 2023-09-19T14:20:45-07:00 New Revision: 87b8c85bba5298fea657b71eb7c75aeb1afa446d URL: https://github.com/llvm/llvm-project/commit/87b8c85bba5298fea657b71eb7c75aeb1afa446d DIFF: https://github.com/llvm/llvm-project/commit/87b8c85bba5298fea657b71eb7c75aeb1afa446d.diff LOG: [-Wunsafe-bugger-usage] Clean tests: remove nondeterministic ordering Differential Review: https://reviews.llvm.org/D158553 Added: Modified: clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-deref-simple-ptr-arith.cpp clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-local-var-span.cpp clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-pointer-deref.cpp clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-pre-increment.cpp clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-unevaluated-context.cpp clang/test/SemaCXX/warn-unsafe-buffer-usage-multi-decl-fixits-test.cpp clang/test/SemaCXX/warn-unsafe-buffer-usage-multi-decl-ptr-init-fixits.cpp clang/test/SemaCXX/warn-unsafe-buffer-usage-multi-decl-ptr-init.cpp clang/test/SemaCXX/warn-unsafe-buffer-usage-multi-decl-uuc-fixits.cpp clang/test/SemaCXX/warn-unsafe-buffer-usage-multi-decl-uuc.cpp clang/test/SemaCXX/warn-unsafe-buffer-usage-multi-decl-warnings.cpp clang/test/SemaCXX/warn-unsafe-buffer-usage-pragma-fixit.cpp clang/test/SemaCXX/warn-unsafe-buffer-usage-source-ranges.cpp Removed: diff --git a/clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-deref-simple-ptr-arith.cpp b/clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-deref-simple-ptr-arith.cpp index 90cfa6842fae8c8..a4a09a0afed595f 100644 --- a/clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-deref-simple-ptr-arith.cpp +++ b/clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-deref-simple-ptr-arith.cpp @@ -10,169 +10,169 @@ void basic() { int *ptr; -// CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:11}:"std::span ptr" +// CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:11}:"std::span ptr" *(ptr+5)=1; -// CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:5}:"" -// CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-2]]:8-[[@LINE-2]]:9}:"[" -// CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-3]]:10-[[@LINE-3]]:11}:"]" +// CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:5}:"" +// CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:8-[[@LINE-2]]:9}:"[" +// CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:10-[[@LINE-3]]:11}:"]" } // The weird preceding semicolon ensures that we preserve that range intact. void char_ranges() { int *p; - // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:9}:"std::span p" + // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:9}:"std::span p" ;* ( p + 5 ) = 1; - // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:4-[[@LINE-1]]:8}:"" - // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-2]]:9-[[@LINE-2]]:12}:"[" - // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-3]]:13-[[@LINE-3]]:15}:"]" + // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:4-[[@LINE-1]]:8}:"" + // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:9-[[@LINE-2]]:12}:"[" + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:13-[[@LINE-3]]:15}:"]" ;* (p+5)= 1; - // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:4-[[@LINE-1]]:9}:"" - // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-2]]:10-[[@LINE-2]]:11}:"[" - // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-3]]:12-[[@LINE-3]]:13}:"]" + // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:4-[[@LINE-1]]:9}:"" + // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:10-[[@LINE-2]]:11}:"[" + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:12-[[@LINE-3]]:13}:"]" ;*( p+5)= 1; - // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:4-[[@LINE-1]]:9}:"" - // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-2]]:10-[[@LINE-2]]:11}:"[" - // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-3]]:12-[[@LINE-3]]:13}:"]" + // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:4-[[@LINE-1]]:9}:"" + // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:10-[[@LINE-2]]:11}:"[" + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:12-[[@LINE-3]]:13}:"]" ;*( p+5)= 1; - // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:4-[[@LINE-1]]:9}:"" - // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-2]]:10-[[@LINE-2]]:11}:"[" - // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-3]]:12-[[@LINE-3]]:13}:"]" + // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:4-[[@LINE-1]]:9}:"" + // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:10-[[@LINE-2]]:11}:"[" + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:12-[[@LINE-3]]:13}:"]" ;*( p +5)= 1; - // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:4-[[@LINE-1]]:7}:"" - // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-2]]:8-[[@LINE-2]]:12}:"[" - // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-3]]:13-[[@LINE-3]]:14}:"]" + // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:4-[[@LINE-1]]:7}:"" + // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:8-[[@LINE-2]]:12}:"[" + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:13-[[@LINE-3]]:14}:"]" ;*(p+ 5)= 1; - // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:4-[[@LINE-1]]:6}:"" - // CHECK-DAG:
[clang] 2afcda6 - [-Wunsafe-buffer-usage] Fix assertion failure in case of BindingDecl
Author: Rashmi Mudduluru Date: 2023-08-17T16:18:38-07:00 New Revision: 2afcda693acba8d63887a6bb0605038b1563c64c URL: https://github.com/llvm/llvm-project/commit/2afcda693acba8d63887a6bb0605038b1563c64c DIFF: https://github.com/llvm/llvm-project/commit/2afcda693acba8d63887a6bb0605038b1563c64c.diff LOG: [-Wunsafe-buffer-usage] Fix assertion failure in case of BindingDecl Differential Revision: https://reviews.llvm.org/D158112#inline-1530312 Added: Modified: clang/lib/Analysis/UnsafeBufferUsage.cpp clang/test/SemaCXX/warn-unsafe-buffer-usage-debug.cpp Removed: diff --git a/clang/lib/Analysis/UnsafeBufferUsage.cpp b/clang/lib/Analysis/UnsafeBufferUsage.cpp index 41820c80da6b4b..2c36d78e60c89b 100644 --- a/clang/lib/Analysis/UnsafeBufferUsage.cpp +++ b/clang/lib/Analysis/UnsafeBufferUsage.cpp @@ -380,6 +380,10 @@ class FixableGadget : public Gadget { } }; +static auto toSupportedVariable() { + return to(varDecl()); +} + using FixableGadgetList = std::vector>; using WarningGadgetList = std::vector>; @@ -566,7 +570,8 @@ class PointerInitGadget : public FixableGadget { static Matcher matcher() { auto PtrInitStmt = declStmt(hasSingleDecl(varDecl( hasInitializer(ignoringImpCasts(declRefExpr( - hasPointerType()). + hasPointerType(), +toSupportedVariable()). bind(PointerInitRHSTag. bind(PointerInitLHSTag))); @@ -616,10 +621,10 @@ class PointerAssignmentGadget : public FixableGadget { static Matcher matcher() { auto PtrAssignExpr = binaryOperator(allOf(hasOperatorName("="), hasRHS(ignoringParenImpCasts(declRefExpr(hasPointerType(), - to(varDecl())). + toSupportedVariable()). bind(PointerAssignRHSTag))), hasLHS(declRefExpr(hasPointerType(), - to(varDecl())). + toSupportedVariable()). bind(PointerAssignLHSTag; return stmt(isInUnspecifiedUntypedContext(PtrAssignExpr)); @@ -691,7 +696,8 @@ class ULCArraySubscriptGadget : public FixableGadget { static Matcher matcher() { auto ArrayOrPtr = anyOf(hasPointerType(), hasArrayType()); auto BaseIsArrayOrPtrDRE = -hasBase(ignoringParenImpCasts(declRefExpr(ArrayOrPtr))); +hasBase(ignoringParenImpCasts(declRefExpr(ArrayOrPtr, + toSupportedVariable(; auto Target = arraySubscriptExpr(BaseIsArrayOrPtrDRE).bind(ULCArraySubscriptTag); @@ -733,7 +739,8 @@ class UPCStandalonePointerGadget : public FixableGadget { static Matcher matcher() { auto ArrayOrPtr = anyOf(hasPointerType(), hasArrayType()); auto target = expr( -ignoringParenImpCasts(declRefExpr(allOf(ArrayOrPtr, to(varDecl(.bind(DeclRefExprTag))); +ignoringParenImpCasts(declRefExpr(allOf(ArrayOrPtr, + toSupportedVariable())).bind(DeclRefExprTag))); return stmt(isInUnspecifiedPointerContext(target)); } @@ -769,7 +776,7 @@ class PointerDereferenceGadget : public FixableGadget { unaryOperator( hasOperatorName("*"), has(expr(ignoringParenImpCasts( -declRefExpr(to(varDecl())).bind(BaseDeclRefExprTag) +declRefExpr(toSupportedVariable()).bind(BaseDeclRefExprTag) .bind(OperatorTag); return expr(isInUnspecifiedLvalueContext(Target)); @@ -809,7 +816,8 @@ class UPCAddressofArraySubscriptGadget : public FixableGadget { return expr(isInUnspecifiedPointerContext(expr(ignoringImpCasts( unaryOperator(hasOperatorName("&"), hasUnaryOperand(arraySubscriptExpr( - hasBase(ignoringParenImpCasts(declRefExpr()) + hasBase(ignoringParenImpCasts(declRefExpr( + toSupportedVariable())) .bind(UPCAddressofArraySubscriptTag); } @@ -961,7 +969,8 @@ class UPCPreIncrementGadget : public FixableGadget { // things right. return stmt(isInUnspecifiedPointerContext(expr(ignoringImpCasts( unaryOperator(isPreInc(), - hasUnaryOperand(declRefExpr()) +
[clang] cf1c64b - [-Wunsafe-buffer-usage] Replace assert that declarations are always found
Author: Rashmi Mudduluru Date: 2023-08-15T15:41:56-07:00 New Revision: cf1c64b94d94105f61e308e57eb963b722d22d77 URL: https://github.com/llvm/llvm-project/commit/cf1c64b94d94105f61e308e57eb963b722d22d77 DIFF: https://github.com/llvm/llvm-project/commit/cf1c64b94d94105f61e308e57eb963b722d22d77.diff LOG: [-Wunsafe-buffer-usage] Replace assert that declarations are always found Differential Revision: https://reviews.llvm.org/D157018 Added: Modified: clang/lib/Analysis/UnsafeBufferUsage.cpp clang/test/SemaCXX/warn-unsafe-buffer-usage-debug.cpp Removed: diff --git a/clang/lib/Analysis/UnsafeBufferUsage.cpp b/clang/lib/Analysis/UnsafeBufferUsage.cpp index 6f9f5f5e7ee7f2..87087686171347 100644 --- a/clang/lib/Analysis/UnsafeBufferUsage.cpp +++ b/clang/lib/Analysis/UnsafeBufferUsage.cpp @@ -888,7 +888,8 @@ class DeclUseTracker { const DeclStmt *lookupDecl(const VarDecl *VD) const { auto It = Defs.find(VD); -assert(It != Defs.end() && "Definition never discovered!"); +if (It == Defs.end()) + return nullptr; return It->second; } }; @@ -2053,7 +2054,10 @@ static FixItList fixVariableWithSpan(const VarDecl *VD, ASTContext , UnsafeBufferUsageHandler ) { const DeclStmt *DS = Tracker.lookupDecl(VD); - assert(DS && "Fixing non-local variables not implemented yet!"); + if (!DS) { +DEBUG_NOTE_DECL_FAIL(VD, " : variables declared this way not implemented yet"); +return {}; + } if (!DS->isSingleDecl()) { // FIXME: to support handling multiple `VarDecl`s in a single `DeclStmt` DEBUG_NOTE_DECL_FAIL(VD, " : multiple VarDecls"); diff --git a/clang/test/SemaCXX/warn-unsafe-buffer-usage-debug.cpp b/clang/test/SemaCXX/warn-unsafe-buffer-usage-debug.cpp index 79031cdb7691d3..f0f9a52cc3d0c9 100644 --- a/clang/test/SemaCXX/warn-unsafe-buffer-usage-debug.cpp +++ b/clang/test/SemaCXX/warn-unsafe-buffer-usage-debug.cpp @@ -66,3 +66,15 @@ void implied_unclaimed_var(int *b) { // expected-warning{{'b' is an unsafe poin b++; // expected-note{{used in pointer arithmetic here}} \ // debug-note{{safe buffers debug: failed to produce fixit for 'b' : has an unclaimed use}} } + +int *a = new int[3]; // expected-warning{{'a' is an unsafe pointer used for buffer access}} \ +// debug-note{{safe buffers debug: failed to produce fixit for 'a' : neither local nor a parameter}} +void test_globals() { + a[7] = 4; // expected-note{{used in buffer access here}} +} + +void test_decomp_decl() { + int a[2] = {1, 2}; + auto [x, y] = a; + x = 9; +} ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] a6ae740 - [-Wunsafe-buffer-usage] Add a facility for debugging low fixit coverage
Author: Rashmi Mudduluru Date: 2023-07-26T17:07:36-07:00 New Revision: a6ae740e743a2241f7104c13152cd0a0582765c5 URL: https://github.com/llvm/llvm-project/commit/a6ae740e743a2241f7104c13152cd0a0582765c5 DIFF: https://github.com/llvm/llvm-project/commit/a6ae740e743a2241f7104c13152cd0a0582765c5.diff LOG: [-Wunsafe-buffer-usage] Add a facility for debugging low fixit coverage Differential Revision: https://reviews.llvm.org/D154880 Added: clang/test/SemaCXX/warn-unsafe-buffer-usage-debug.cpp Modified: clang/include/clang/Analysis/Analyses/UnsafeBufferUsage.h clang/include/clang/Basic/DiagnosticSemaKinds.td clang/lib/Analysis/UnsafeBufferUsage.cpp clang/lib/Sema/AnalysisBasedWarnings.cpp Removed: diff --git a/clang/include/clang/Analysis/Analyses/UnsafeBufferUsage.h b/clang/include/clang/Analysis/Analyses/UnsafeBufferUsage.h index 6766ba8ec2..13f28076c6f4d7 100644 --- a/clang/include/clang/Analysis/Analyses/UnsafeBufferUsage.h +++ b/clang/include/clang/Analysis/Analyses/UnsafeBufferUsage.h @@ -16,6 +16,7 @@ #include "clang/AST/Decl.h" #include "clang/AST/Stmt.h" +#include "llvm/Support/Debug.h" namespace clang { @@ -24,6 +25,18 @@ using DefMapTy = llvm::DenseMap>; /// The interface that lets the caller handle unsafe buffer usage analysis /// results by overriding this class's handle... methods. class UnsafeBufferUsageHandler { +#ifndef NDEBUG +public: + // A self-debugging facility that you can use to notify the user when + // suggestions or fixits are incomplete. + // Uses std::function to avoid computing the message when it won't + // actually be displayed. + using DebugNote = std::pair; + using DebugNoteList = std::vector; + using DebugNoteByVar = std::map; + DebugNoteByVar DebugNotesByVar; +#endif + public: UnsafeBufferUsageHandler() = default; virtual ~UnsafeBufferUsageHandler() = default; @@ -43,6 +56,26 @@ class UnsafeBufferUsageHandler { const DefMapTy , FixItList &) = 0; +#ifndef NDEBUG +public: + bool areDebugNotesRequested() { +DEBUG_WITH_TYPE("SafeBuffers", return true); +return false; + } + + void addDebugNoteForVar(const VarDecl *VD, SourceLocation Loc, + std::string Text) { +if (areDebugNotesRequested()) + DebugNotesByVar[VD].push_back(std::make_pair(Loc, Text)); + } + + void clearDebugNotes() { +if (areDebugNotesRequested()) + DebugNotesByVar.clear(); + } +#endif + +public: /// Returns a reference to the `Preprocessor`: virtual bool isSafeBufferOptOut(const SourceLocation ) const = 0; diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index c88f25209fc0fa..b531babf0449c4 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -11872,6 +11872,12 @@ def note_unsafe_buffer_variable_fixit_group : Note< "change type of %0 to '%select{std::span|std::array|std::span::iterator}1' to preserve bounds information%select{|, and change %2 to '%select{std::span|std::array|std::span::iterator}1' to propagate bounds information between them}3">; def note_safe_buffer_usage_suggestions_disabled : Note< "pass -fsafe-buffer-usage-suggestions to receive code hardening suggestions">; +#ifndef NDEBUG +// Not a user-facing diagnostic. Useful for debugging false negatives in +// -fsafe-buffer-usage-suggestions (i.e. lack of -Wunsafe-buffer-usage fixits). +def note_safe_buffer_debug_mode : Note<"safe buffers debug: %0">; +#endif + def err_loongarch_builtin_requires_la32 : Error< "this builtin requires target: loongarch32">; diff --git a/clang/lib/Analysis/UnsafeBufferUsage.cpp b/clang/lib/Analysis/UnsafeBufferUsage.cpp index 7b1c5107a7e049..781dc13c898d22 100644 --- a/clang/lib/Analysis/UnsafeBufferUsage.cpp +++ b/clang/lib/Analysis/UnsafeBufferUsage.cpp @@ -316,6 +316,15 @@ class Gadget { Kind getKind() const { return K; } +#ifndef NDEBUG + StringRef getDebugName() const { +switch (K) { +#define GADGET(x) case Kind::x: return #x; +#include "clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def" +} + } +#endif + virtual bool isWarningGadget() const = 0; virtual const Stmt *getBaseStmt() const = 0; @@ -565,7 +574,11 @@ class PointerInitGadget : public FixableGadget { virtual std::optional getFixits(const Strategy ) const override; - virtual const Stmt *getBaseStmt() const override { return nullptr; } + virtual const Stmt *getBaseStmt() const override { +// FIXME: This needs to be the entire DeclStmt, assuming that this method +// makes sense at all on a FixableGadget. +return PtrInitRHS; + } virtual DeclUseList getClaimedVarUseSites() const override { return DeclUseList{PtrInitRHS}; @@ -613,7 +626,11 @@ class
[clang] 070358e - [-Wunsafe-buffer-usage] Fix a fallthrough case in UPCStandalonePointer getFixits
Author: Rashmi Mudduluru Date: 2023-07-25T13:40:33-07:00 New Revision: 070358ec92350c13b0b6c60fbb03bf35a7a00251 URL: https://github.com/llvm/llvm-project/commit/070358ec92350c13b0b6c60fbb03bf35a7a00251 DIFF: https://github.com/llvm/llvm-project/commit/070358ec92350c13b0b6c60fbb03bf35a7a00251.diff LOG: [-Wunsafe-buffer-usage] Fix a fallthrough case in UPCStandalonePointer getFixits Differential Revision: https://reviews.llvm.org/D155526 Added: clang/test/SemaCXX/warn-unsafe-buffer-usage-test-unreachable.cpp Modified: clang/lib/Analysis/UnsafeBufferUsage.cpp Removed: diff --git a/clang/lib/Analysis/UnsafeBufferUsage.cpp b/clang/lib/Analysis/UnsafeBufferUsage.cpp index 5cde60cefdf065..78f180447eef6f 100644 --- a/clang/lib/Analysis/UnsafeBufferUsage.cpp +++ b/clang/lib/Analysis/UnsafeBufferUsage.cpp @@ -1512,8 +1512,8 @@ PointerDereferenceGadget::getFixits(const Strategy ) const { FixItHint::CreateInsertion( (*EndOfOperand).getLocWithOffset(1), "[0]")}}; } +break; } -[[fallthrough]]; case Strategy::Kind::Iterator: case Strategy::Kind::Array: case Strategy::Kind::Vector: @@ -1541,8 +1541,9 @@ std::optional UPCStandalonePointerGadget::getFixits(const Strategy if (EndOfOperand) return FixItList{{FixItHint::CreateInsertion( *EndOfOperand, ".data()")}}; + // FIXME: Points inside a macro expansion. + break; } - [[fallthrough]]; case Strategy::Kind::Wontfix: case Strategy::Kind::Iterator: case Strategy::Kind::Array: diff --git a/clang/test/SemaCXX/warn-unsafe-buffer-usage-test-unreachable.cpp b/clang/test/SemaCXX/warn-unsafe-buffer-usage-test-unreachable.cpp new file mode 100644 index 00..844311c3a51a58 --- /dev/null +++ b/clang/test/SemaCXX/warn-unsafe-buffer-usage-test-unreachable.cpp @@ -0,0 +1,8 @@ +// RUN: %clang_cc1 -std=c++20 -Wunsafe-buffer-usage -fsafe-buffer-usage-suggestions -verify %s + +// expected-no-diagnostics + +typedef unsigned __darwin_size_t; +typedef __darwin_size_t size_t; + #define bzero(s, n) __builtin_bzero(s, n) +void __nosan_bzero(void *dst, size_t sz) { bzero(dst, sz); } ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] 27c1033 - [WIP][-Wunsafe-buffer-usage] Handle lambda expressions within a method.
Author: Rashmi Mudduluru Date: 2023-07-20T10:00:16-07:00 New Revision: 27c10337831c94ef59f8790f6ca1c3d1b66b4494 URL: https://github.com/llvm/llvm-project/commit/27c10337831c94ef59f8790f6ca1c3d1b66b4494 DIFF: https://github.com/llvm/llvm-project/commit/27c10337831c94ef59f8790f6ca1c3d1b66b4494.diff LOG: [WIP][-Wunsafe-buffer-usage] Handle lambda expressions within a method. Differential Revision: https://reviews.llvm.org/D150386 Added: Modified: clang/docs/LibASTMatchersReference.html clang/docs/ReleaseNotes.rst clang/include/clang/ASTMatchers/ASTMatchers.h clang/lib/ASTMatchers/ASTMatchersInternal.cpp clang/lib/ASTMatchers/Dynamic/Registry.cpp clang/lib/Analysis/UnsafeBufferUsage.cpp clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-pointer-access.cpp clang/test/SemaCXX/warn-unsafe-buffer-usage.cpp Removed: diff --git a/clang/docs/LibASTMatchersReference.html b/clang/docs/LibASTMatchersReference.html index bde8ac7de52a73..b4f282fbf43816 100644 --- a/clang/docs/LibASTMatchersReference.html +++ b/clang/docs/LibASTMatchersReference.html @@ -1257,6 +1257,43 @@ Node Matchers +Matcherhttps://clang.llvm.org/doxygen/classclang_1_1Stmt.html;>StmtarrayInitIndexExprMatcherhttps://clang.llvm.org/doxygen/classclang_1_1ArrayInitIndexExpr.html;>ArrayInitIndexExpr... +The arrayInitIndexExpr consists of two subexpressions: a common expression +(the source array) that is evaluated once up-front, and a per-element initializer +that runs once for each array element. Within the per-element initializer, +the current index may be obtained via an ArrayInitIndexExpr. + +Given + void testStructBinding() { +int a[2] = {1, 2}; +auto [x, y] = a; + } +arrayInitIndexExpr() matches the array index that implicitly iterates +over the array `a` to copy each element to the anonymous array +that backs the structured binding `[x, y]` elements of which are +referred to by their aliases `x` and `y`. + + + +Matcherhttps://clang.llvm.org/doxygen/classclang_1_1Stmt.html;>StmtarrayInitLoopExprMatcherhttps://clang.llvm.org/doxygen/classclang_1_1ArrayInitLoopExpr.html;>ArrayInitLoopExpr... +Matches a loop initializing the elements of an array in a number of contexts: + * in the implicit copy/move constructor for a class with an array member + * when a lambda-expression captures an array by value + * when a decomposition declaration decomposes an array + +Given + void testLambdaCapture() { +int a[10]; +auto Lam1 = [a]() { + return; +}; + } +arrayInitLoopExpr() matches the implicit loop that initializes each element of +the implicit array field inside the lambda object, that represents the array `a` +captured by value. + + + Matcherhttps://clang.llvm.org/doxygen/classclang_1_1Stmt.html;>StmtarraySubscriptExprMatcherhttps://clang.llvm.org/doxygen/classclang_1_1ArraySubscriptExpr.html;>ArraySubscriptExpr... Matches array subscript expressions. diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index ef1cc898c21f6d..f1d098ef02f41d 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -943,6 +943,8 @@ AST Matchers - The ``hasBody`` matcher now matches coroutine body nodes in ``CoroutineBodyStmts``. + +- Add ``arrayInitIndexExpr`` and ``arrayInitLoopExpr`` matchers. clang-format diff --git a/clang/include/clang/ASTMatchers/ASTMatchers.h b/clang/include/clang/ASTMatchers/ASTMatchers.h index b698365f949bfa..a9313139226ca4 100644 --- a/clang/include/clang/ASTMatchers/ASTMatchers.h +++ b/clang/include/clang/ASTMatchers/ASTMatchers.h @@ -1971,6 +1971,45 @@ extern const internal::VariadicDynCastAllOfMatcher extern const internal::VariadicDynCastAllOfMatcher cxxNoexceptExpr; +/// Matches a loop initializing the elements of an array in a number of contexts: +/// * in the implicit copy/move constructor for a class with an array member +/// * when a lambda-expression captures an array by value +/// * when a decomposition declaration decomposes an array +/// +/// Given +/// \code +/// void testLambdaCapture() { +/// int a[10]; +/// auto Lam1 = [a]() { +/// return; +/// }; +/// } +/// \endcode +/// arrayInitLoopExpr() matches the implicit loop that initializes each element of +/// the implicit array field inside the lambda object, that represents the array `a` +/// captured by value. +extern const internal::VariadicDynCastAllOfMatcher +arrayInitLoopExpr; + +/// The arrayInitIndexExpr consists of two subexpressions: a common expression +/// (the source array) that is evaluated once up-front, and a per-element initializer +/// that runs once for each array element. Within the per-element initializer, +/// the current index may be obtained via an ArrayInitIndexExpr. +/// +/// Given +/// \code +/// void testStructBinding() { +/// int a[2] = {1, 2}; +/// auto [x, y] = a;
[clang] 1e62587 - [clang][docs] Defensively turn off exception behavior in dump_ast_matchers.py
Author: Rashmi Mudduluru Date: 2023-07-18T15:36:09-07:00 New Revision: 1e62587a48a33b3bf5939e1eef2fd4e41b7e75f6 URL: https://github.com/llvm/llvm-project/commit/1e62587a48a33b3bf5939e1eef2fd4e41b7e75f6 DIFF: https://github.com/llvm/llvm-project/commit/1e62587a48a33b3bf5939e1eef2fd4e41b7e75f6.diff LOG: [clang][docs] Defensively turn off exception behavior in dump_ast_matchers.py Differential Revision: https://reviews.llvm.org/D155134 Added: Modified: clang/docs/tools/dump_ast_matchers.py Removed: diff --git a/clang/docs/tools/dump_ast_matchers.py b/clang/docs/tools/dump_ast_matchers.py index 8ac3c2166d4231..cc7024d1627b97 100755 --- a/clang/docs/tools/dump_ast_matchers.py +++ b/clang/docs/tools/dump_ast_matchers.py @@ -15,7 +15,8 @@ try: CLASS_INDEX_PAGE = urlopen(CLASS_INDEX_PAGE_URL).read().decode("utf-8") except Exception as e: -raise Exception("Unable to get %s: %s" % (CLASS_INDEX_PAGE_URL, e)) +CLASS_INDEX_PAGE = None +print("Unable to get %s: %s" % (CLASS_INDEX_PAGE_URL, e)) MATCHERS_FILE = "../../include/clang/ASTMatchers/ASTMatchers.h" @@ -58,7 +59,10 @@ def link_if_exists(m): url = "https://clang.llvm.org/doxygen/classclang_1_1%s.html; % name if url not in doxygen_probes: search_str = 'href="classclang_1_1%s.html"' % name -doxygen_probes[url] = search_str in CLASS_INDEX_PAGE +if CLASS_INDEX_PAGE is not None: +doxygen_probes[url] = search_str in CLASS_INDEX_PAGE +else: +doxygen_probes[url] = True if not doxygen_probes[url]: print("Did not find %s in class index page" % name) if doxygen_probes[url]: @@ -186,7 +190,7 @@ def act_on_decl(declaration, comment, allowed_types): """ if declaration.strip(): -if re.match(r"^\s?(#|namespace|using)", declaration): +if re.match(r"^\s?(#|namespace|using|template using|})", declaration): return # Node matchers are defined by writing: ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] 3ea673a - [clang][docs] Update LibASTMatchersReference.html
Author: Rashmi Mudduluru Date: 2023-07-18T15:27:59-07:00 New Revision: 3ea673a97b0583affc22345b9d62e863ba36b3d8 URL: https://github.com/llvm/llvm-project/commit/3ea673a97b0583affc22345b9d62e863ba36b3d8 DIFF: https://github.com/llvm/llvm-project/commit/3ea673a97b0583affc22345b9d62e863ba36b3d8.diff LOG: [clang][docs] Update LibASTMatchersReference.html Differential Revision: https://reviews.llvm.org/D155304 Added: Modified: clang/docs/LibASTMatchersReference.html Removed: diff --git a/clang/docs/LibASTMatchersReference.html b/clang/docs/LibASTMatchersReference.html index e6b8c771f1a394..bde8ac7de52a73 100644 --- a/clang/docs/LibASTMatchersReference.html +++ b/clang/docs/LibASTMatchersReference.html @@ -1455,6 +1455,16 @@ Node Matchers +Matcherhttps://clang.llvm.org/doxygen/classclang_1_1Stmt.html;>StmtcoroutineBodyStmtMatcherhttps://clang.llvm.org/doxygen/classclang_1_1CoroutineBodyStmt.html;>CoroutineBodyStmt... +Matches coroutine body statements. + +coroutineBodyStmt() matches the coroutine below + generatorint gen() { +co_return; + } + + + Matcherhttps://clang.llvm.org/doxygen/classclang_1_1Stmt.html;>StmtcoyieldExprMatcherhttps://clang.llvm.org/doxygen/classclang_1_1CoyieldExpr.html;>CoyieldExpr... Matches co_yield expressions. @@ -3037,10 +3047,11 @@ Narrowing Matchers Matcherhttps://clang.llvm.org/doxygen/classclang_1_1CXXConstructExpr.html;>CXXConstructExprargumentCountAtLeastunsigned N -Checks that a call expression or a constructor call expression has -at least the specified number of arguments (including absent default arguments). +Checks that a call expression or a constructor call expression has at least +the specified number of arguments (including absent default arguments). -Example matches f(0, 0) and g(0, 0, 0) (matcher = callExpr(argumentCountAtLeast(2))) +Example matches f(0, 0) and g(0, 0, 0) +(matcher = callExpr(argumentCountAtLeast(2))) void f(int x, int y); void g(int x, int y, int z); f(0, 0); @@ -3706,10 +3717,11 @@ Narrowing Matchers Matcherhttps://clang.llvm.org/doxygen/classclang_1_1CXXUnresolvedConstructExpr.html;>CXXUnresolvedConstructExprargumentCountAtLeastunsigned N -Checks that a call expression or a constructor call expression has -at least the specified number of arguments (including absent default arguments). +Checks that a call expression or a constructor call expression has at least +the specified number of arguments (including absent default arguments). -Example matches f(0, 0) and g(0, 0, 0) (matcher = callExpr(argumentCountAtLeast(2))) +Example matches f(0, 0) and g(0, 0, 0) +(matcher = callExpr(argumentCountAtLeast(2))) void f(int x, int y); void g(int x, int y, int z); f(0, 0); @@ -3728,10 +3740,11 @@ Narrowing Matchers Matcherhttps://clang.llvm.org/doxygen/classclang_1_1CallExpr.html;>CallExprargumentCountAtLeastunsigned N -Checks that a call expression or a constructor call expression has -at least the specified number of arguments (including absent default arguments). +Checks that a call expression or a constructor call expression has at least +the specified number of arguments (including absent default arguments). -Example matches f(0, 0) and g(0, 0, 0) (matcher = callExpr(argumentCountAtLeast(2))) +Example matches f(0, 0) and g(0, 0, 0) +(matcher = callExpr(argumentCountAtLeast(2))) void f(int x, int y); void g(int x, int y, int z); f(0, 0); @@ -4897,10 +4910,11 @@ Narrowing Matchers Matcherhttps://clang.llvm.org/doxygen/classclang_1_1ObjCMessageExpr.html;>ObjCMessageExprargumentCountAtLeastunsigned N -Checks that a call expression or a constructor call expression has -at least the specified number of arguments (including absent default arguments). +Checks that a call expression or a constructor call expression has at least +the specified number of arguments (including absent default arguments). -Example matches f(0, 0) and g(0, 0, 0) (matcher = callExpr(argumentCountAtLeast(2))) +Example matches f(0, 0) and g(0, 0, 0) +(matcher = callExpr(argumentCountAtLeast(2))) void f(int x, int y); void g(int x, int y, int z); f(0, 0); @@ -6795,9 +6809,10 @@ AST Traversal Matchers Matcherhttps://clang.llvm.org/doxygen/classclang_1_1CXXForRangeStmt.html;>CXXForRangeStmthasBodyMatcherhttps://clang.llvm.org/doxygen/classclang_1_1Stmt.html;>Stmt InnerMatcher -Matches a 'for', 'while', 'do' statement or a function definition that has -a given body. Note that in case of functions this matcher only matches the -definition itself and not the other declarations of the same function. +Matches a 'for', 'while', 'while' statement or a function or coroutine +definition that has a given body. Note that in case of functions or +coroutines this matcher only matches the definition itself and not the +other declarations of the same function or coroutine. Given for
[clang] db3dced - [-Wunsafe-buffer-usage] Handle pointer initializations for grouping related variables
Author: Rashmi Mudduluru Date: 2023-06-21T15:54:09-07:00 New Revision: db3dcedb9cedcec4a9570fda7406490c642df8ae URL: https://github.com/llvm/llvm-project/commit/db3dcedb9cedcec4a9570fda7406490c642df8ae DIFF: https://github.com/llvm/llvm-project/commit/db3dcedb9cedcec4a9570fda7406490c642df8ae.diff LOG: [-Wunsafe-buffer-usage] Handle pointer initializations for grouping related variables Differential Revision: https://reviews.llvm.org/D150489 Added: clang/test/SemaCXX/warn-unsafe-buffer-usage-multi-decl-ptr-init-fixits.cpp clang/test/SemaCXX/warn-unsafe-buffer-usage-multi-decl-ptr-init.cpp Modified: clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def clang/lib/Analysis/UnsafeBufferUsage.cpp clang/test/SemaCXX/warn-unsafe-buffer-usage-multi-decl-uuc-fixits.cpp clang/test/SemaCXX/warn-unsafe-buffer-usage-multi-decl-uuc.cpp clang/test/SemaCXX/warn-unsafe-buffer-usage-multi-decl-warnings.cpp Removed: diff --git a/clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def b/clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def index 57d9dcc5bdcb7..ff687a0d178bd 100644 --- a/clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def +++ b/clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def @@ -37,6 +37,7 @@ FIXABLE_GADGET(UPCAddressofArraySubscript) // '[any]' in an Unspecified Poin FIXABLE_GADGET(UPCStandalonePointer) FIXABLE_GADGET(UPCPreIncrement)// '++Ptr' in an Unspecified Pointer Context FIXABLE_GADGET(PointerAssignment) +FIXABLE_GADGET(PointerInit) #undef FIXABLE_GADGET #undef WARNING_GADGET diff --git a/clang/lib/Analysis/UnsafeBufferUsage.cpp b/clang/lib/Analysis/UnsafeBufferUsage.cpp index 49229a6b56c1c..aa29fb45726a8 100644 --- a/clang/lib/Analysis/UnsafeBufferUsage.cpp +++ b/clang/lib/Analysis/UnsafeBufferUsage.cpp @@ -533,23 +533,66 @@ class PointerArithmeticGadget : public WarningGadget { // FIXME: this gadge will need a fix-it }; +/// A pointer initialization expression of the form: +/// \code +/// int *p = q; +/// \endcode +class PointerInitGadget : public FixableGadget { +private: + static constexpr const char *const PointerInitLHSTag = "ptrInitLHS"; + static constexpr const char *const PointerInitRHSTag = "ptrInitRHS"; + const VarDecl * PtrInitLHS; // the LHS pointer expression in `PI` + const DeclRefExpr * PtrInitRHS; // the RHS pointer expression in `PI` + +public: + PointerInitGadget(const MatchFinder::MatchResult ) + : FixableGadget(Kind::PointerInit), +PtrInitLHS(Result.Nodes.getNodeAs(PointerInitLHSTag)), +PtrInitRHS(Result.Nodes.getNodeAs(PointerInitRHSTag)) {} + + static bool classof(const Gadget *G) { +return G->getKind() == Kind::PointerInit; + } + + static Matcher matcher() { +auto PtrInitStmt = declStmt(hasSingleDecl(varDecl( + hasInitializer(ignoringImpCasts(declRefExpr( + hasPointerType()). + bind(PointerInitRHSTag. + bind(PointerInitLHSTag))); + +return stmt(PtrInitStmt); + } + + virtual std::optional getFixits(const Strategy ) const override; + + virtual const Stmt *getBaseStmt() const override { return nullptr; } + + virtual DeclUseList getClaimedVarUseSites() const override { +return DeclUseList{PtrInitRHS}; + } + + virtual std::optional> + getStrategyImplications() const override { + return std::make_pair(PtrInitLHS, +cast(PtrInitRHS->getDecl())); + } +}; + /// A pointer assignment expression of the form: /// \code /// p = q; /// \endcode class PointerAssignmentGadget : public FixableGadget { private: - static constexpr const char *const PointerAssignmentTag = "ptrAssign"; static constexpr const char *const PointerAssignLHSTag = "ptrLHS"; static constexpr const char *const PointerAssignRHSTag = "ptrRHS"; - const BinaryOperator *PA;// pointer arithmetic expression const DeclRefExpr * PtrLHS; // the LHS pointer expression in `PA` const DeclRefExpr * PtrRHS; // the RHS pointer expression in `PA` public: PointerAssignmentGadget(const MatchFinder::MatchResult ) : FixableGadget(Kind::PointerAssignment), -PA(Result.Nodes.getNodeAs(PointerAssignmentTag)), PtrLHS(Result.Nodes.getNodeAs(PointerAssignLHSTag)), PtrRHS(Result.Nodes.getNodeAs(PointerAssignRHSTag)) {} @@ -566,13 +609,12 @@ class PointerAssignmentGadget : public FixableGadget { to(varDecl())). bind(PointerAssignLHSTag; -//FIXME: Handle declarations at assignments return stmt(isInUnspecifiedUntypedContext(PtrAssignExpr)); } virtual
[clang] d1ae844 - [-Wunsafe-buffer-usage] Do not emit fixits for C++ interfaces with C linkage
Author: Rashmi Mudduluru Date: 2023-06-16T13:28:34-07:00 New Revision: d1ae844dc2cc58bc762135d9500464c61d50f4f9 URL: https://github.com/llvm/llvm-project/commit/d1ae844dc2cc58bc762135d9500464c61d50f4f9 DIFF: https://github.com/llvm/llvm-project/commit/d1ae844dc2cc58bc762135d9500464c61d50f4f9.diff LOG: [-Wunsafe-buffer-usage] Do not emit fixits for C++ interfaces with C linkage Differential Revision: https://reviews.llvm.org/D153064 Added: clang/test/SemaCXX/warn-unsafe-buffer-usage-c-linkage.cpp Modified: clang/lib/Analysis/UnsafeBufferUsage.cpp Removed: diff --git a/clang/lib/Analysis/UnsafeBufferUsage.cpp b/clang/lib/Analysis/UnsafeBufferUsage.cpp index 999b94a070368..49229a6b56c1c 100644 --- a/clang/lib/Analysis/UnsafeBufferUsage.cpp +++ b/clang/lib/Analysis/UnsafeBufferUsage.cpp @@ -2139,6 +2139,18 @@ void clang::checkUnsafeBufferUsage(const Decl *D, UnsafeBufferUsageHandler , bool EmitSuggestions) { assert(D && D->getBody()); + + // Do not emit fixit suggestions for functions declared in an + // extern "C" block. + if (const auto *FD = dyn_cast(D)) { + for (FunctionDecl *FReDecl : FD->redecls()) { + if (FReDecl->isExternC()) { +EmitSuggestions = false; +break; + } +} + } + WarningGadgetSets UnsafeOps; FixableGadgetSets FixablesForAllVars; diff --git a/clang/test/SemaCXX/warn-unsafe-buffer-usage-c-linkage.cpp b/clang/test/SemaCXX/warn-unsafe-buffer-usage-c-linkage.cpp new file mode 100644 index 0..6c134098f87df --- /dev/null +++ b/clang/test/SemaCXX/warn-unsafe-buffer-usage-c-linkage.cpp @@ -0,0 +1,24 @@ +// RUN: %clang_cc1 -std=c++20 -Wunsafe-buffer-usage -fsafe-buffer-usage-suggestions -verify %s + +extern "C" { +void foo(int *ptr) { + ptr[5] = 10; // expected-warning{{unsafe buffer access}} +} + +void bar(int *ptr); + +struct c_struct { + char *name; +}; +} + +void bar(int *ptr) { + ptr[5] = 10; // expected-warning{{unsafe buffer access}} +} + +void call_foo(int *p) { + foo(p); + struct c_struct str; + str.name[7] = 9; // expected-warning{{unsafe buffer access}} + bar(p); +} ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] 171dfc5 - [-Wunsafe-buffer-usage] Group variables associated by pointer assignments
Author: Rashmi Mudduluru Date: 2023-05-25T11:31:27-07:00 New Revision: 171dfc5462a23b7e8ace31f4d9206b972b38ffbc URL: https://github.com/llvm/llvm-project/commit/171dfc5462a23b7e8ace31f4d9206b972b38ffbc DIFF: https://github.com/llvm/llvm-project/commit/171dfc5462a23b7e8ace31f4d9206b972b38ffbc.diff LOG: [-Wunsafe-buffer-usage] Group variables associated by pointer assignments Differential Revision: https://reviews.llvm.org/D145739 Added: clang/test/SemaCXX/warn-unsafe-buffer-usage-multi-decl-fixits-test.cpp clang/test/SemaCXX/warn-unsafe-buffer-usage-multi-decl-uuc-fixits.cpp clang/test/SemaCXX/warn-unsafe-buffer-usage-multi-decl-uuc.cpp clang/test/SemaCXX/warn-unsafe-buffer-usage-multi-decl-warnings.cpp Modified: clang/include/clang/Analysis/Analyses/UnsafeBufferUsage.h clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def clang/include/clang/Basic/DiagnosticSemaKinds.td clang/lib/Analysis/UnsafeBufferUsage.cpp clang/lib/Sema/AnalysisBasedWarnings.cpp Removed: diff --git a/clang/include/clang/Analysis/Analyses/UnsafeBufferUsage.h b/clang/include/clang/Analysis/Analyses/UnsafeBufferUsage.h index 10635e8f3a29f..617bc7c77c565 100644 --- a/clang/include/clang/Analysis/Analyses/UnsafeBufferUsage.h +++ b/clang/include/clang/Analysis/Analyses/UnsafeBufferUsage.h @@ -19,6 +19,8 @@ namespace clang { +using DefMapTy = llvm::DenseMap>; + /// The interface that lets the caller handle unsafe buffer usage analysis /// results by overriding this class's handle... methods. class UnsafeBufferUsageHandler { @@ -34,9 +36,12 @@ class UnsafeBufferUsageHandler { virtual void handleUnsafeOperation(const Stmt *Operation, bool IsRelatedToDecl) = 0; - /// Invoked when a fix is suggested against a variable. - virtual void handleFixableVariable(const VarDecl *Variable, - FixItList &) = 0; + /// Invoked when a fix is suggested against a variable. This function groups + /// all variables that must be fixed together (i.e their types must be changed to the + /// same target type to prevent type mismatches) into a single fixit. + virtual void handleUnsafeVariableGroup(const VarDecl *Variable, + const DefMapTy , + FixItList &) = 0; /// Returns a reference to the `Preprocessor`: virtual bool isSafeBufferOptOut(const SourceLocation ) const = 0; diff --git a/clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def b/clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def index a112b6d105025..57d9dcc5bdcb7 100644 --- a/clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def +++ b/clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def @@ -36,6 +36,7 @@ FIXABLE_GADGET(PointerDereference) FIXABLE_GADGET(UPCAddressofArraySubscript) // '[any]' in an Unspecified Pointer Context FIXABLE_GADGET(UPCStandalonePointer) FIXABLE_GADGET(UPCPreIncrement)// '++Ptr' in an Unspecified Pointer Context +FIXABLE_GADGET(PointerAssignment) #undef FIXABLE_GADGET #undef WARNING_GADGET diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index f203ac6c2a84e..a777d43f1468f 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -11822,8 +11822,8 @@ def warn_unsafe_buffer_operation : Warning< InGroup, DefaultIgnore; def note_unsafe_buffer_operation : Note< "used%select{| in pointer arithmetic| in buffer access}0 here">; -def note_unsafe_buffer_variable_fixit : Note< - "change type of '%0' to '%select{std::span|std::array|std::span::iterator}1' to preserve bounds information">; +def note_unsafe_buffer_variable_fixit_group : Note< + "change type of %0 to '%select{std::span|std::array|std::span::iterator}1' to preserve bounds information%select{|, and change %2 to '%select{std::span|std::array|std::span::iterator}1' to propagate bounds information between them}3">; def note_safe_buffer_usage_suggestions_disabled : Note< "pass -fsafe-buffer-usage-suggestions to receive code hardening suggestions">; def err_loongarch_builtin_requires_la32 : Error< diff --git a/clang/lib/Analysis/UnsafeBufferUsage.cpp b/clang/lib/Analysis/UnsafeBufferUsage.cpp index 87e3ec90dbf2f..c9cc4ccbfb5d5 100644 --- a/clang/lib/Analysis/UnsafeBufferUsage.cpp +++ b/clang/lib/Analysis/UnsafeBufferUsage.cpp @@ -16,6 +16,7 @@ #include #include #include +#include using namespace llvm; using namespace clang; @@ -256,6 +257,29 @@ isInUnspecifiedPointerContext(internal::Matcher InnerMatcher) { // FIXME: any more cases? (UPC excludes the RHS of an assignment. For now we // don't have to check that.) } + +// Returns a matcher that matches any expression
[clang] ee6b08e - [-Wunsafe-buffer-usage] Group variables associated by pointer assignments
Author: Rashmi Mudduluru Date: 2023-05-24T16:20:55-07:00 New Revision: ee6b08e99375fc48d1e5848704a66c2e8e57eb3b URL: https://github.com/llvm/llvm-project/commit/ee6b08e99375fc48d1e5848704a66c2e8e57eb3b DIFF: https://github.com/llvm/llvm-project/commit/ee6b08e99375fc48d1e5848704a66c2e8e57eb3b.diff LOG: [-Wunsafe-buffer-usage] Group variables associated by pointer assignments Differential Revision: https://reviews.llvm.org/D145739 Added: clang/test/SemaCXX/warn-unsafe-buffer-usage-multi-decl-fixits-test.cpp clang/test/SemaCXX/warn-unsafe-buffer-usage-multi-decl-uuc-fixits.cpp clang/test/SemaCXX/warn-unsafe-buffer-usage-multi-decl-uuc.cpp clang/test/SemaCXX/warn-unsafe-buffer-usage-multi-decl-warnings.cpp Modified: clang/include/clang/Analysis/Analyses/UnsafeBufferUsage.h clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def clang/include/clang/Basic/DiagnosticSemaKinds.td clang/lib/Analysis/UnsafeBufferUsage.cpp clang/lib/Sema/AnalysisBasedWarnings.cpp Removed: diff --git a/clang/include/clang/Analysis/Analyses/UnsafeBufferUsage.h b/clang/include/clang/Analysis/Analyses/UnsafeBufferUsage.h index 10635e8f3a29f..617bc7c77c565 100644 --- a/clang/include/clang/Analysis/Analyses/UnsafeBufferUsage.h +++ b/clang/include/clang/Analysis/Analyses/UnsafeBufferUsage.h @@ -19,6 +19,8 @@ namespace clang { +using DefMapTy = llvm::DenseMap>; + /// The interface that lets the caller handle unsafe buffer usage analysis /// results by overriding this class's handle... methods. class UnsafeBufferUsageHandler { @@ -34,9 +36,12 @@ class UnsafeBufferUsageHandler { virtual void handleUnsafeOperation(const Stmt *Operation, bool IsRelatedToDecl) = 0; - /// Invoked when a fix is suggested against a variable. - virtual void handleFixableVariable(const VarDecl *Variable, - FixItList &) = 0; + /// Invoked when a fix is suggested against a variable. This function groups + /// all variables that must be fixed together (i.e their types must be changed to the + /// same target type to prevent type mismatches) into a single fixit. + virtual void handleUnsafeVariableGroup(const VarDecl *Variable, + const DefMapTy , + FixItList &) = 0; /// Returns a reference to the `Preprocessor`: virtual bool isSafeBufferOptOut(const SourceLocation ) const = 0; diff --git a/clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def b/clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def index a112b6d105025..57d9dcc5bdcb7 100644 --- a/clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def +++ b/clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def @@ -36,6 +36,7 @@ FIXABLE_GADGET(PointerDereference) FIXABLE_GADGET(UPCAddressofArraySubscript) // '[any]' in an Unspecified Pointer Context FIXABLE_GADGET(UPCStandalonePointer) FIXABLE_GADGET(UPCPreIncrement)// '++Ptr' in an Unspecified Pointer Context +FIXABLE_GADGET(PointerAssignment) #undef FIXABLE_GADGET #undef WARNING_GADGET diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index f203ac6c2a84e..a777d43f1468f 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -11822,8 +11822,8 @@ def warn_unsafe_buffer_operation : Warning< InGroup, DefaultIgnore; def note_unsafe_buffer_operation : Note< "used%select{| in pointer arithmetic| in buffer access}0 here">; -def note_unsafe_buffer_variable_fixit : Note< - "change type of '%0' to '%select{std::span|std::array|std::span::iterator}1' to preserve bounds information">; +def note_unsafe_buffer_variable_fixit_group : Note< + "change type of %0 to '%select{std::span|std::array|std::span::iterator}1' to preserve bounds information%select{|, and change %2 to '%select{std::span|std::array|std::span::iterator}1' to propagate bounds information between them}3">; def note_safe_buffer_usage_suggestions_disabled : Note< "pass -fsafe-buffer-usage-suggestions to receive code hardening suggestions">; def err_loongarch_builtin_requires_la32 : Error< diff --git a/clang/lib/Analysis/UnsafeBufferUsage.cpp b/clang/lib/Analysis/UnsafeBufferUsage.cpp index 87e3ec90dbf2f..c9cc4ccbfb5d5 100644 --- a/clang/lib/Analysis/UnsafeBufferUsage.cpp +++ b/clang/lib/Analysis/UnsafeBufferUsage.cpp @@ -16,6 +16,7 @@ #include #include #include +#include using namespace llvm; using namespace clang; @@ -256,6 +257,29 @@ isInUnspecifiedPointerContext(internal::Matcher InnerMatcher) { // FIXME: any more cases? (UPC excludes the RHS of an assignment. For now we // don't have to check that.) } + +// Returns a matcher that matches any expression
[clang] acc3cc6 - [-Wunsafe-buffer-usage] Introduce the unsafe_buffer_usage attribute
Author: Rashmi Mudduluru Date: 2023-01-31T11:43:34-08:00 New Revision: acc3cc69e4d1c8e199fde51798a5a2a6edb35796 URL: https://github.com/llvm/llvm-project/commit/acc3cc69e4d1c8e199fde51798a5a2a6edb35796 DIFF: https://github.com/llvm/llvm-project/commit/acc3cc69e4d1c8e199fde51798a5a2a6edb35796.diff LOG: [-Wunsafe-buffer-usage] Introduce the unsafe_buffer_usage attribute Differential Revision: https://reviews.llvm.org/D138940 Added: clang/test/SemaCXX/attr-unsafe-buffer-usage.cpp clang/test/SemaCXX/warn-unsafe-buffer-usage-function-attr.cpp Modified: clang/docs/ReleaseNotes.rst clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def clang/include/clang/Basic/Attr.td clang/include/clang/Basic/AttrDocs.td clang/include/clang/Basic/DiagnosticSemaKinds.td clang/lib/Analysis/UnsafeBufferUsage.cpp clang/lib/Sema/AnalysisBasedWarnings.cpp clang/lib/Sema/SemaDeclAttr.cpp clang/test/Misc/pragma-attribute-supported-attributes-list.test Removed: diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 0a1197044a71a..c6139252e0c34 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -89,6 +89,11 @@ New Pragmas in Clang Attribute Changes in Clang -- +Introduced a new function attribute ``__attribute__((unsafe_buffer_usage))`` +to be worn by functions containing buffer operations that could cause out of +bounds memory accesses. It emits warnings at call sites to such functions when +the flag ``-Wunsafe-buffer-usage`` is enabled. + Windows Support --- diff --git a/clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def b/clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def index d10d95e5b1ba7..78889da32b3b4 100644 --- a/clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def +++ b/clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def @@ -29,6 +29,7 @@ WARNING_GADGET(Increment) WARNING_GADGET(Decrement) WARNING_GADGET(ArraySubscript) WARNING_GADGET(PointerArithmetic) +WARNING_GADGET(UnsafeBufferUsageAttr) #undef FIXABLE_GADGET #undef WARNING_GADGET diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index d449a2fe7f8f7..fc2c7f7e37f45 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -3966,6 +3966,12 @@ def ReleaseHandle : InheritableParamAttr { let Documentation = [ReleaseHandleDocs]; } +def UnsafeBufferUsage : InheritableAttr { + let Spellings = [Clang<"unsafe_buffer_usage">]; + let Subjects = SubjectList<[Function]>; + let Documentation = [UnsafeBufferUsageDocs]; +} + def DiagnoseAsBuiltin : InheritableAttr { let Spellings = [Clang<"diagnose_as_builtin">]; let Args = [DeclArgument, diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td index 6d7a3ffd2d52c..b0b11e85ab6ad 100644 --- a/clang/include/clang/Basic/AttrDocs.td +++ b/clang/include/clang/Basic/AttrDocs.td @@ -6274,6 +6274,82 @@ attribute requires a string literal argument to identify the handle being releas }]; } +def UnsafeBufferUsageDocs : Documentation { + let Content = [{ +The attribute ``[[clang::unsafe_buffer_usage]]`` should be placed on functions +that need to be avoided as they are prone to buffer overflows. It is designed to +work together with the off-by-default compiler warning ``-Wunsafe-buffer-usage`` +to help codebases transition away from raw pointer based buffer management, +in favor of safer abstractions such as C++20 ``std::span``. The attribute causes +``-Wunsafe-buffer-usage`` to warn on every use of the function, and it may +enable ``-Wunsafe-buffer-usage`` to emit automatic fix-it hints +which would help the user replace such unsafe functions with safe +alternatives, though the attribute can be used even when the fix can't be automated. + +The attribute does not suppress ``-Wunsafe-buffer-usage`` inside the function +to which it is attached. These warnings still need to be addressed. + +The attribute is warranted even if the only way a function can overflow +the buffer is by violating the function's preconditions. For example, it +would make sense to put the attribute on function ``foo()`` below because +passing an incorrect size parameter would cause a buffer overflow: + +.. code-block:: c++ + [[clang::unsafe_buffer_usage]] + void foo(int *buf, size_t size) { +for (size_t i = 0; i < size; ++i) { + buf[i] = i; +} + } + +The attribute is NOT warranted when the function uses safe abstractions, +assuming that these abstractions weren't misused outside the function. +For example, function ``bar()`` below doesn't need the attribute, +because assuming that the container ``buf`` is well-formed (has size that +fits the original buffer it refers to), overflow cannot occur: + +.. code-block:: c++ +
[clang] fe93da2 - [-Wunsafe-buffer-usage] Emit warnings about unsafe operations on arrays
Author: Rashmi Mudduluru Date: 2023-01-17T16:30:13-08:00 New Revision: fe93da22aa7bd57e277571cd692c7c0cc51c0478 URL: https://github.com/llvm/llvm-project/commit/fe93da22aa7bd57e277571cd692c7c0cc51c0478 DIFF: https://github.com/llvm/llvm-project/commit/fe93da22aa7bd57e277571cd692c7c0cc51c0478.diff LOG: [-Wunsafe-buffer-usage] Emit warnings about unsafe operations on arrays Differential Revision: https://reviews.llvm.org/D141725/new/ Added: Modified: clang/lib/Analysis/UnsafeBufferUsage.cpp clang/test/SemaCXX/warn-unsafe-buffer-usage.cpp Removed: diff --git a/clang/lib/Analysis/UnsafeBufferUsage.cpp b/clang/lib/Analysis/UnsafeBufferUsage.cpp index 97f81368273e9..fa72d20bea6fe 100644 --- a/clang/lib/Analysis/UnsafeBufferUsage.cpp +++ b/clang/lib/Analysis/UnsafeBufferUsage.cpp @@ -133,6 +133,10 @@ static auto hasPointerType() { return hasType(hasCanonicalType(pointerType())); } +static auto hasArrayType() { +return hasType(hasCanonicalType(arrayType())); +} + namespace { /// Gadget is an individual operation in the code that may be of interest to /// this analysis. Each (non-abstract) subclass corresponds to a specific @@ -292,9 +296,13 @@ class ArraySubscriptGadget : public WarningGadget { static Matcher matcher() { // FIXME: What if the index is integer literal 0? Should this be // a safe gadget in this case? -return stmt(arraySubscriptExpr(hasBase(ignoringParenImpCasts(hasPointerType())), - unless(hasIndex(integerLiteral(equals(0) -.bind(ArraySubscrTag)); + // clang-format off + return stmt(arraySubscriptExpr( +hasBase(ignoringParenImpCasts( + anyOf(hasPointerType(), hasArrayType(, +unless(hasIndex(integerLiteral(equals(0) +.bind(ArraySubscrTag)); + // clang-format on } const ArraySubscriptExpr *getBaseStmt() const override { return ASE; } @@ -516,7 +524,8 @@ static std::tuple findGadg #include "clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def" // In parallel, match all DeclRefExprs so that to find out // whether there are any uncovered by gadgets. -declRefExpr(hasPointerType(), to(varDecl())).bind("any_dre"), +declRefExpr(anyOf(hasPointerType(), hasArrayType()), +to(varDecl())).bind("any_dre"), // Also match DeclStmts because we'll need them when fixing // their underlying VarDecls that otherwise don't have // any backreferences to DeclStmts. diff --git a/clang/test/SemaCXX/warn-unsafe-buffer-usage.cpp b/clang/test/SemaCXX/warn-unsafe-buffer-usage.cpp index 476ec73c4f744..87831334746aa 100644 --- a/clang/test/SemaCXX/warn-unsafe-buffer-usage.cpp +++ b/clang/test/SemaCXX/warn-unsafe-buffer-usage.cpp @@ -49,11 +49,10 @@ void testArraySubscripts(int *p, int **pp) { int a[10], b[10][10]; - // Not to warn subscripts on arrays - foo(a[1], 1[a], - b[3][4], - 4[b][3], - 4[3[b]]); + foo(a[1], 1[a], // expected-warning2{{unchecked operation on raw buffer in expression}} + b[3][4], // expected-warning2{{unchecked operation on raw buffer in expression}} + 4[b][3], // expected-warning2{{unchecked operation on raw buffer in expression}} + 4[3[b]]); // expected-warning2{{unchecked operation on raw buffer in expression}} // Not to warn when index is zero foo(p[0], pp[0][0], 0[0[pp]], 0[pp][0], @@ -96,8 +95,7 @@ void testQualifiedParameters(const int * p, const int * const q, foo(p[1], 1[p], p[-1], // expected-warning3{{unchecked operation on raw buffer in expression}} q[1], 1[q], q[-1], // expected-warning3{{unchecked operation on raw buffer in expression}} a[1],// expected-warning{{unchecked operation on raw buffer in expression}} `a` is of pointer type - b[1][2], // expected-warning{{unchecked operation on raw buffer in expression}} `b[1]` is of array type - c[1] // `c` is of array type + b[1][2] // expected-warning2{{unchecked operation on raw buffer in expression}} `b[1]` is of array type ); } @@ -116,27 +114,27 @@ T_t funRetT(); T_t * funRetTStar(); void testStructMembers(struct T * sp, struct T s, T_t * sp2, T_t s2) { - foo(sp->a[1], - sp->b[1], // expected-warning{{unchecked operation on raw buffer in expression}} - sp->c.a[1], - sp->c.b[1], // expected-warning{{unchecked operation on raw buffer in expression}} - s.a[1], - s.b[1], // expected-warning{{unchecked operation on raw buffer in expression}} - s.c.a[1], - s.c.b[1], // expected-warning{{unchecked operation on raw buffer in expression}} - sp2->a[1], - sp2->b[1],// expected-warning{{unchecked operation on raw buffer in expression}} - sp2->c.a[1], -
[clang-tools-extra] 13bc713 - fixes clang-tidy/checks/list.rst: a line was accidentally removed in 95a92995d45fc6fada43ecd91eba3e7aea90487a
Author: Rashmi Mudduluru Date: 2022-08-05T12:36:03-07:00 New Revision: 13bc71310920dced155328e25aa382dc2bb1ef9f URL: https://github.com/llvm/llvm-project/commit/13bc71310920dced155328e25aa382dc2bb1ef9f DIFF: https://github.com/llvm/llvm-project/commit/13bc71310920dced155328e25aa382dc2bb1ef9f.diff LOG: fixes clang-tidy/checks/list.rst: a line was accidentally removed in 95a92995d45fc6fada43ecd91eba3e7aea90487a Added: Modified: clang-tools-extra/docs/clang-tidy/checks/list.rst Removed: diff --git a/clang-tools-extra/docs/clang-tidy/checks/list.rst b/clang-tools-extra/docs/clang-tidy/checks/list.rst index b72e3ca69c39d..a7c6247ab96bf 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/list.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/list.rst @@ -239,6 +239,7 @@ Clang-Tidy Checks `llvmlibc-implementation-in-namespace `_, `llvmlibc-restrict-system-libc-headers `_, "Yes" `misc-confusable-identifiers `_, + `misc-const-correctness `_, "Yes" `misc-definitions-in-headers `_, "Yes" `misc-misleading-bidirectional `_, `misc-misleading-identifier `_, ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] 95a9299 - Adds the NSDateFormatter checker to clang-tidy
Author: Rashmi Mudduluru Date: 2022-08-02T13:57:44-07:00 New Revision: 95a92995d45fc6fada43ecd91eba3e7aea90487a URL: https://github.com/llvm/llvm-project/commit/95a92995d45fc6fada43ecd91eba3e7aea90487a DIFF: https://github.com/llvm/llvm-project/commit/95a92995d45fc6fada43ecd91eba3e7aea90487a.diff LOG: Adds the NSDateFormatter checker to clang-tidy Differential Revision: https://reviews.llvm.org/D126097 Added: clang-tools-extra/clang-tidy/objc/NSDateFormatterCheck.cpp clang-tools-extra/clang-tidy/objc/NSDateFormatterCheck.h clang-tools-extra/docs/clang-tidy/checks/objc/nsdate-formatter.rst clang-tools-extra/test/clang-tidy/checkers/objc/nsdate-formatter.m Modified: clang-tools-extra/clang-tidy/objc/CMakeLists.txt clang-tools-extra/clang-tidy/objc/ObjCTidyModule.cpp clang-tools-extra/docs/clang-tidy/checks/list.rst Removed: diff --git a/clang-tools-extra/clang-tidy/objc/CMakeLists.txt b/clang-tools-extra/clang-tidy/objc/CMakeLists.txt index 1129c6aa729f..bdd125c97cc0 100644 --- a/clang-tools-extra/clang-tidy/objc/CMakeLists.txt +++ b/clang-tools-extra/clang-tidy/objc/CMakeLists.txt @@ -10,6 +10,7 @@ add_clang_library(clangTidyObjCModule ForbiddenSubclassingCheck.cpp MissingHashCheck.cpp NSInvocationArgumentLifetimeCheck.cpp + NSDateFormatterCheck.cpp ObjCTidyModule.cpp PropertyDeclarationCheck.cpp SuperSelfCheck.cpp diff --git a/clang-tools-extra/clang-tidy/objc/NSDateFormatterCheck.cpp b/clang-tools-extra/clang-tidy/objc/NSDateFormatterCheck.cpp new file mode 100644 index ..fdc837704a69 --- /dev/null +++ b/clang-tools-extra/clang-tidy/objc/NSDateFormatterCheck.cpp @@ -0,0 +1,116 @@ +//===--- NSDateFormatterCheck.cpp - clang-tidy ===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--===// + +#include "NSDateFormatterCheck.h" +#include "clang/AST/ASTContext.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" +#include "clang/ASTMatchers/ASTMatchers.h" + +using namespace clang::ast_matchers; + +namespace clang { +namespace tidy { +namespace objc { + +void NSDateFormatterCheck::registerMatchers(MatchFinder *Finder) { + // Adding matchers. + + Finder->addMatcher( + objcMessageExpr(hasSelector("setDateFormat:"), + hasReceiverType(asString("NSDateFormatter *")), + hasArgument(0, ignoringImpCasts( + objcStringLiteral().bind("str_lit", + this); +} + +static char ValidDatePatternChars[] = { +'G', 'y', 'Y', 'u', 'U', 'r', 'Q', 'q', 'M', 'L', 'I', 'w', 'W', 'd', +'D', 'F', 'g', 'E', 'e', 'c', 'a', 'b', 'B', 'h', 'H', 'K', 'k', 'j', +'J', 'C', 'm', 's', 'S', 'A', 'z', 'Z', 'O', 'v', 'V', 'X', 'x'}; + +// Checks if the string pattern used as a date format specifier is valid. +// A string pattern is valid if all the letters(a-z, A-Z) in it belong to the +// set of reserved characters. See: +// https://www.unicode.org/reports/tr35/tr35.html#Invalid_Patterns +bool isValidDatePattern(StringRef Pattern) { + for (auto : Pattern) { +if (isalpha(PatternChar)) { + if (std::find(std::begin(ValidDatePatternChars), +std::end(ValidDatePatternChars), +PatternChar) == std::end(ValidDatePatternChars)) { +return false; + } +} + } + return true; +} + +// Checks if the string pattern used as a date format specifier contains +// any incorrect pattern and reports it as a warning. +// See: http://www.unicode.org/reports/tr35/tr35-dates.html#Date_Format_Patterns +void NSDateFormatterCheck::check(const MatchFinder::MatchResult ) { + // Callback implementation. + const auto *StrExpr = Result.Nodes.getNodeAs("str_lit"); + const StringLiteral *SL = cast(StrExpr)->getString(); + StringRef SR = SL->getString(); + + if (!isValidDatePattern(SR)) { +diag(StrExpr->getExprLoc(), "invalid date format specifier"); + } + + if (SR.contains('y') && SR.contains('w') && !SR.contains('Y')) { +diag(StrExpr->getExprLoc(), + "use of calendar year (y) with week of the year (w); " + "did you mean to use week-year (Y) instead?"); + } + if (SR.contains('F')) { +if (!(SR.contains('e') || SR.contains('E'))) { + diag(StrExpr->getExprLoc(), + "day of week in month (F) used without day of the week (e or E); " + "did you forget e (or E) in the format string?"); +} +if (!SR.contains('M')) { + diag(StrExpr->getExprLoc(), + "day of week in month (F) used without the month (M); " + "did you forget M in the format string?"); +} + } + if (SR.contains('W') && !SR.contains('M')) {
[clang] eb1d908 - Adds AST matcher for ObjCStringLiteral
Author: Rashmi Mudduluru Date: 2022-06-30T15:20:10-07:00 New Revision: eb1d908e5cf7279b98b84d1587d4665d3cdecbe9 URL: https://github.com/llvm/llvm-project/commit/eb1d908e5cf7279b98b84d1587d4665d3cdecbe9 DIFF: https://github.com/llvm/llvm-project/commit/eb1d908e5cf7279b98b84d1587d4665d3cdecbe9.diff LOG: Adds AST matcher for ObjCStringLiteral Differential Revision: https://reviews.llvm.org/D128103 Added: Modified: clang/docs/LibASTMatchersReference.html clang/docs/ReleaseNotes.rst clang/include/clang/ASTMatchers/ASTMatchers.h clang/lib/ASTMatchers/ASTMatchersInternal.cpp clang/lib/ASTMatchers/Dynamic/Registry.cpp clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp Removed: diff --git a/clang/docs/LibASTMatchersReference.html b/clang/docs/LibASTMatchersReference.html index c206c63e84acb..03ca48cc1a9b3 100644 --- a/clang/docs/LibASTMatchersReference.html +++ b/clang/docs/LibASTMatchersReference.html @@ -1236,7 +1236,7 @@ Node Matchers #pragma omp parallel ``ompDefaultClause()`` matches ``default(none)``, ``default(shared)``, -``default(private)`` and ``default(firstprivate)`` +`` default(private)`` and ``default(firstprivate)`` @@ -2036,6 +2036,14 @@ Node Matchers +Matcherhttps://clang.llvm.org/doxygen/classclang_1_1Stmt.html;>StmtobjcStringLiteralMatcherhttps://clang.llvm.org/doxygen/classclang_1_1ObjCStringLiteral.html;>ObjCStringLiteral... +Matches ObjectiveC String literal expressions. + +Example matches @"abcd" + NSString *s = @"abcd"; + + + Matcherhttps://clang.llvm.org/doxygen/classclang_1_1Stmt.html;>StmtobjcThrowStmtMatcherhttps://clang.llvm.org/doxygen/classclang_1_1ObjCAtThrowStmt.html;>ObjCAtThrowStmt... Matches Objective-C statements. @@ -4716,8 +4724,8 @@ Narrowing Matchers -Matcherhttps://clang.llvm.org/doxygen/classclang_1_1OMPDefaultClause.html;>OMPDefaultClauseisFirstPrivateKind -Matches if the OpenMP ``default`` clause has ``private`` kind +Matcherhttps://clang.llvm.org/doxygen/classclang_1_1OMPDefaultClause.html;>OMPDefaultClauseisFirstPrivateKind +Matches if the OpenMP ``default`` clause has ``firstprivate`` kind specified. Given @@ -4729,12 +4737,12 @@ Narrowing Matchers #pragma omp parallel default(firstprivate) ``ompDefaultClause(isFirstPrivateKind())`` matches only -``default(private)``. +``default(firstprivate)``. -Matcherhttps://clang.llvm.org/doxygen/classclang_1_1OMPDefaultClause.html;>OMPDefaultClauseisFirstPrivateKind -Matches if the OpenMP ``default`` clause has ``firstprivate`` kind -specified. + +Matcherhttps://clang.llvm.org/doxygen/classclang_1_1OMPDefaultClause.html;>OMPDefaultClauseisNoneKind +Matches if the OpenMP ``default`` clause has ``none`` kind specified. Given @@ -4744,13 +4752,13 @@ Narrowing Matchers #pragma omp parallel default(private) #pragma omp parallel default(firstprivate) -``ompDefaultClause(isFirstPrivateKind())`` matches only -``default(firstprivate)``. +``ompDefaultClause(isNoneKind())`` matches only ``default(none)``. -Matcherhttps://clang.llvm.org/doxygen/classclang_1_1OMPDefaultClause.html;>OMPDefaultClauseisNoneKind -Matches if the OpenMP ``default`` clause has ``none`` kind specified. +Matcherhttps://clang.llvm.org/doxygen/classclang_1_1OMPDefaultClause.html;>OMPDefaultClauseisPrivateKind +Matches if the OpenMP ``default`` clause has ``private`` kind +specified. Given @@ -4760,7 +4768,8 @@ Narrowing Matchers #pragma omp parallel default(private) #pragma omp parallel default(firstprivate) -``ompDefaultClause(isNoneKind())`` matches only ``default(none)``. +``ompDefaultClause(isPrivateKind())`` matches only +``default(private)``. @@ -7411,8 +7420,9 @@ AST Traversal Matchers -Matcherhttps://clang.llvm.org/doxygen/classclang_1_1ClassTemplateSpecializationDecl.html;>ClassTemplateSpecializationDeclforEachTemplateArgumentMatcherhttps://clang.llvm.org/doxygen/classclang_1_1TemplateArgument.html;>TemplateArgument InnerMatcher -Matches classTemplateSpecialization, templateSpecializationType and functionDecl nodes where the template argument matches the inner matcher. +Matcherhttps://clang.llvm.org/doxygen/classclang_1_1ClassTemplateSpecializationDecl.html;>ClassTemplateSpecializationDeclforEachTemplateArgumentclang::ast_matchers::Matcherhttps://clang.llvm.org/doxygen/classclang_1_1TemplateArgument.html;>TemplateArgument InnerMatcher +Matches classTemplateSpecialization, templateSpecializationType and +functionDecl nodes where the template argument matches the inner matcher. This matcher may produce multiple matches. Given @@ -7427,10 +7437,8 @@ AST Traversal Matchers bool B = false; f(R, B); - templateSpecializationType(forEachTemplateArgument(isExpr(expr( matches twice, with expr() matching 'R * 2' and 'R * 4' - functionDecl(forEachTemplateArgument(refersToType(builtinType( matches the specialization
[clang] 572e2cd - Reverting ce420820c815e806bab9c5f17cb3b829a616548a because it fails expensive checks
Author: Rashmi Mudduluru Date: 2022-02-16T09:25:53-08:00 New Revision: 572e2cd56a43429bdbc88c886e260b5facff9048 URL: https://github.com/llvm/llvm-project/commit/572e2cd56a43429bdbc88c886e260b5facff9048 DIFF: https://github.com/llvm/llvm-project/commit/572e2cd56a43429bdbc88c886e260b5facff9048.diff LOG: Reverting ce420820c815e806bab9c5f17cb3b829a616548a because it fails expensive checks Added: Modified: clang/test/Analysis/trustnonnullchecker_test.m Removed: diff --git a/clang/test/Analysis/trustnonnullchecker_test.m b/clang/test/Analysis/trustnonnullchecker_test.m index 5e09c4f6dde21..cb0c1cdcab61a 100644 --- a/clang/test/Analysis/trustnonnullchecker_test.m +++ b/clang/test/Analysis/trustnonnullchecker_test.m @@ -1,3 +1,6 @@ +// Temporarily disabling the test, it failes the "system is over-constrained" (part of expensive checks) +// assertion in *non* optimized builds. +// REQUIRES: rdar44992170 // RUN: %clang_analyze_cc1 -fblocks -analyze -analyzer-checker=core,nullability,apiModeling,debug.ExprInspection -verify %s #include "Inputs/system-header-simulator-for-nullability.h" ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] ce42082 - [Analyzer] Re-enables trustnonnullchecker_test.m
Author: Rashmi Mudduluru Date: 2022-02-10T18:52:48-08:00 New Revision: ce420820c815e806bab9c5f17cb3b829a616548a URL: https://github.com/llvm/llvm-project/commit/ce420820c815e806bab9c5f17cb3b829a616548a DIFF: https://github.com/llvm/llvm-project/commit/ce420820c815e806bab9c5f17cb3b829a616548a.diff LOG: [Analyzer] Re-enables trustnonnullchecker_test.m Differential review: https://reviews.llvm.org/D119270 Added: Modified: clang/test/Analysis/trustnonnullchecker_test.m Removed: diff --git a/clang/test/Analysis/trustnonnullchecker_test.m b/clang/test/Analysis/trustnonnullchecker_test.m index 81eac863d5eb..4240502cbbdd 100644 --- a/clang/test/Analysis/trustnonnullchecker_test.m +++ b/clang/test/Analysis/trustnonnullchecker_test.m @@ -1,6 +1,3 @@ -// Temporarily disabling the test, it failes the "system is over-constrained" -// assertion in *non* optimized builds. -// REQUIRES: rdar44992170 // RUN: %clang_analyze_cc1 -fblocks -analyze -analyzer-checker=core,nullability,apiModeling,debug.ExprInspection -verify %s #include "Inputs/system-header-simulator-for-nullability.h" ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits