[clang] [Clang] Optimize -Wunsafe-buffer-usage. (PR #124554)
https://github.com/ivanaivanovska closed https://github.com/llvm/llvm-project/pull/124554 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Optimize -Wunsafe-buffer-usage. (PR #125492)
https://github.com/ivanaivanovska ready_for_review https://github.com/llvm/llvm-project/pull/125492 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Optimize -Wunsafe-buffer-usage. (PR #125492)
https://github.com/ivanaivanovska created https://github.com/llvm/llvm-project/pull/125492 None >From 54c7b3c1fb149b82c26927d0fd831d8786f70ac3 Mon Sep 17 00:00:00 2001 From: Ivana Ivanovska Date: Mon, 2 Dec 2024 14:17:06 + Subject: [PATCH] Optimize -Wunsafe-buffer-usage. --- clang/lib/Analysis/UnsafeBufferUsage.cpp | 1427 ++ 1 file changed, 906 insertions(+), 521 deletions(-) diff --git a/clang/lib/Analysis/UnsafeBufferUsage.cpp b/clang/lib/Analysis/UnsafeBufferUsage.cpp index c064aa30e8aedc..4520d28d9e9452 100644 --- a/clang/lib/Analysis/UnsafeBufferUsage.cpp +++ b/clang/lib/Analysis/UnsafeBufferUsage.cpp @@ -8,30 +8,32 @@ #include "clang/Analysis/Analyses/UnsafeBufferUsage.h" #include "clang/AST/ASTContext.h" +#include "clang/AST/ASTTypeTraits.h" #include "clang/AST/Decl.h" +#include "clang/AST/DeclCXX.h" #include "clang/AST/DynamicRecursiveASTVisitor.h" #include "clang/AST/Expr.h" #include "clang/AST/FormatString.h" +#include "clang/AST/ParentMapContext.h" #include "clang/AST/Stmt.h" #include "clang/AST/StmtVisitor.h" #include "clang/AST/Type.h" -#include "clang/ASTMatchers/ASTMatchFinder.h" -#include "clang/ASTMatchers/ASTMatchers.h" #include "clang/Basic/SourceLocation.h" #include "clang/Lex/Lexer.h" #include "clang/Lex/Preprocessor.h" #include "llvm/ADT/APSInt.h" +#include "llvm/ADT/STLFunctionalExtras.h" +#include "llvm/ADT/SmallSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/Casting.h" -#include #include #include +#include #include using namespace llvm; using namespace clang; -using namespace ast_matchers; #ifndef NDEBUG namespace { @@ -68,7 +70,7 @@ static std::string getDREAncestorString(const DeclRefExpr *DRE, if (StParents.size() > 1) return "unavailable due to multiple parents"; -if (StParents.size() == 0) +if (StParents.empty()) break; St = StParents.begin()->get(); if (St) @@ -76,10 +78,39 @@ static std::string getDREAncestorString(const DeclRefExpr *DRE, } while (St); return SS.str(); } + } // namespace #endif /* NDEBUG */ -namespace clang::ast_matchers { +namespace { +// Using a custom matcher instead of ASTMatchers to achieve better performance. +class FastMatcher { +public: + virtual bool matches(const DynTypedNode &DynNode, ASTContext &Ctx, + const UnsafeBufferUsageHandler &Handler) = 0; + virtual ~FastMatcher() = default; +}; + +class MatchResult { + +public: + template const T *getNodeAs(StringRef ID) const { +auto It = Nodes.find(std::string(ID)); +if (It == Nodes.end()) { + return nullptr; +} +return It->second.get(); + } + + void addNode(StringRef ID, const DynTypedNode &Node) { +Nodes[std::string(ID)] = Node; + } + +private: + llvm::StringMap Nodes; +}; +} // namespace + // A `RecursiveASTVisitor` that traverses all descendants of a given node "n" // except for those belonging to a different callable of "n". class MatchDescendantVisitor : public DynamicRecursiveASTVisitor { @@ -87,13 +118,11 @@ class MatchDescendantVisitor : public DynamicRecursiveASTVisitor { // Creates an AST visitor that matches `Matcher` on all // descendants of a given node "n" except for the ones // belonging to a different callable of "n". - MatchDescendantVisitor(const internal::DynTypedMatcher *Matcher, - internal::ASTMatchFinder *Finder, - internal::BoundNodesTreeBuilder *Builder, - internal::ASTMatchFinder::BindKind Bind, + MatchDescendantVisitor(FastMatcher &Matcher, bool FindAll, const bool ignoreUnevaluatedContext) - : Matcher(Matcher), Finder(Finder), Builder(Builder), Bind(Bind), -Matches(false), ignoreUnevaluatedContext(ignoreUnevaluatedContext) { + : Matcher(&Matcher), FindAll(FindAll), Matches(false), +ignoreUnevaluatedContext(ignoreUnevaluatedContext), +ActiveASTContext(nullptr), Handler(nullptr) { ShouldVisitTemplateInstantiations = true; ShouldVisitImplicitCode = false; // TODO: let's ignore implicit code for now } @@ -104,7 +133,6 @@ class MatchDescendantVisitor : public DynamicRecursiveASTVisitor { Matches = false; if (const Stmt *StmtNode = DynNode.get()) { TraverseStmt(const_cast(StmtNode)); - *Builder = ResultBindings; return Matches; } return false; @@ -186,106 +214,212 @@ class MatchDescendantVisitor : public DynamicRecursiveASTVisitor { return DynamicRecursiveASTVisitor::TraverseStmt(Node); } + void setASTContext(ASTContext &Context) { ActiveASTContext = &Context; } + + void setHandler(const UnsafeBufferUsageHandler &NewHandler) { +Handler = &NewHandler; + } + private: // Sets 'Matched' to true if 'Matcher' matches 'Node' // // Returns 'true' if traversal should continue after this function // returns, i.e. if no match is found or 'Bind'
[clang] [Clang] Optimize -Wunsafe-buffer-usage. (PR #125492)
https://github.com/ivanaivanovska edited https://github.com/llvm/llvm-project/pull/125492 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Optimize -Wunsafe-buffer-usage. (PR #124554)
@@ -68,32 +70,60 @@ static std::string getDREAncestorString(const DeclRefExpr *DRE, if (StParents.size() > 1) return "unavailable due to multiple parents"; -if (StParents.size() == 0) +if (StParents.empty()) break; St = StParents.begin()->get(); if (St) SS << " ==> "; } while (St); return SS.str(); } + } // namespace #endif /* NDEBUG */ -namespace clang::ast_matchers { +namespace { +// Using a custom matcher instead of ASTMatchers to achieve better performance. +class FastMatcher { +public: + virtual bool matches(const DynTypedNode &DynNode, ASTContext &Ctx, + const UnsafeBufferUsageHandler &Handler) = 0; + virtual ~FastMatcher() = default; +}; + +class MatchResult { + +public: + template const T *getNodeAs(StringRef ID) const { +auto It = Nodes.find(std::string(ID)); +if (It == Nodes.end()) { + return nullptr; +} +return It->second.get(); + } + + void addNode(StringRef ID, const DynTypedNode &Node) { +Nodes[std::string(ID)] = Node; + } + +private: + llvm::StringMap + Nodes; // DynTypedNode needed to store different types of Nodes, not + // necessarily sharing the same base. +}; +} // namespace + // A `RecursiveASTVisitor` that traverses all descendants of a given node "n" // except for those belonging to a different callable of "n". class MatchDescendantVisitor : public DynamicRecursiveASTVisitor { public: // Creates an AST visitor that matches `Matcher` on all // descendants of a given node "n" except for the ones // belonging to a different callable of "n". - MatchDescendantVisitor(const internal::DynTypedMatcher *Matcher, - internal::ASTMatchFinder *Finder, - internal::BoundNodesTreeBuilder *Builder, - internal::ASTMatchFinder::BindKind Bind, + MatchDescendantVisitor(FastMatcher &Matcher, bool FindAll, const bool ignoreUnevaluatedContext) - : Matcher(Matcher), Finder(Finder), Builder(Builder), Bind(Bind), -Matches(false), ignoreUnevaluatedContext(ignoreUnevaluatedContext) { + : Matcher(&Matcher), FindAll(FindAll), Matches(false), +ignoreUnevaluatedContext(ignoreUnevaluatedContext) { ivanaivanovska wrote: Done. https://github.com/llvm/llvm-project/pull/124554 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Optimize -Wunsafe-buffer-usage. (PR #124554)
@@ -68,32 +70,60 @@ static std::string getDREAncestorString(const DeclRefExpr *DRE, if (StParents.size() > 1) return "unavailable due to multiple parents"; -if (StParents.size() == 0) +if (StParents.empty()) break; St = StParents.begin()->get(); if (St) SS << " ==> "; } while (St); return SS.str(); } + } // namespace #endif /* NDEBUG */ -namespace clang::ast_matchers { +namespace { +// Using a custom matcher instead of ASTMatchers to achieve better performance. +class FastMatcher { +public: + virtual bool matches(const DynTypedNode &DynNode, ASTContext &Ctx, + const UnsafeBufferUsageHandler &Handler) = 0; + virtual ~FastMatcher() = default; +}; + +class MatchResult { + +public: + template const T *getNodeAs(StringRef ID) const { +auto It = Nodes.find(std::string(ID)); +if (It == Nodes.end()) { + return nullptr; +} +return It->second.get(); + } + + void addNode(StringRef ID, const DynTypedNode &Node) { +Nodes[std::string(ID)] = Node; + } + +private: + llvm::StringMap + Nodes; // DynTypedNode needed to store different types of Nodes, not ivanaivanovska wrote: Done. https://github.com/llvm/llvm-project/pull/124554 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Optimize -Wunsafe-buffer-usage. (PR #124554)
https://github.com/ivanaivanovska edited https://github.com/llvm/llvm-project/pull/124554 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Optimize -Wunsafe-buffer-usage. (PR #125492)
https://github.com/ivanaivanovska updated https://github.com/llvm/llvm-project/pull/125492 >From 54c7b3c1fb149b82c26927d0fd831d8786f70ac3 Mon Sep 17 00:00:00 2001 From: Ivana Ivanovska Date: Mon, 2 Dec 2024 14:17:06 + Subject: [PATCH 1/2] Optimize -Wunsafe-buffer-usage. --- clang/lib/Analysis/UnsafeBufferUsage.cpp | 1427 ++ 1 file changed, 906 insertions(+), 521 deletions(-) diff --git a/clang/lib/Analysis/UnsafeBufferUsage.cpp b/clang/lib/Analysis/UnsafeBufferUsage.cpp index c064aa30e8aedc6..4520d28d9e94522 100644 --- a/clang/lib/Analysis/UnsafeBufferUsage.cpp +++ b/clang/lib/Analysis/UnsafeBufferUsage.cpp @@ -8,30 +8,32 @@ #include "clang/Analysis/Analyses/UnsafeBufferUsage.h" #include "clang/AST/ASTContext.h" +#include "clang/AST/ASTTypeTraits.h" #include "clang/AST/Decl.h" +#include "clang/AST/DeclCXX.h" #include "clang/AST/DynamicRecursiveASTVisitor.h" #include "clang/AST/Expr.h" #include "clang/AST/FormatString.h" +#include "clang/AST/ParentMapContext.h" #include "clang/AST/Stmt.h" #include "clang/AST/StmtVisitor.h" #include "clang/AST/Type.h" -#include "clang/ASTMatchers/ASTMatchFinder.h" -#include "clang/ASTMatchers/ASTMatchers.h" #include "clang/Basic/SourceLocation.h" #include "clang/Lex/Lexer.h" #include "clang/Lex/Preprocessor.h" #include "llvm/ADT/APSInt.h" +#include "llvm/ADT/STLFunctionalExtras.h" +#include "llvm/ADT/SmallSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/Casting.h" -#include #include #include +#include #include using namespace llvm; using namespace clang; -using namespace ast_matchers; #ifndef NDEBUG namespace { @@ -68,7 +70,7 @@ static std::string getDREAncestorString(const DeclRefExpr *DRE, if (StParents.size() > 1) return "unavailable due to multiple parents"; -if (StParents.size() == 0) +if (StParents.empty()) break; St = StParents.begin()->get(); if (St) @@ -76,10 +78,39 @@ static std::string getDREAncestorString(const DeclRefExpr *DRE, } while (St); return SS.str(); } + } // namespace #endif /* NDEBUG */ -namespace clang::ast_matchers { +namespace { +// Using a custom matcher instead of ASTMatchers to achieve better performance. +class FastMatcher { +public: + virtual bool matches(const DynTypedNode &DynNode, ASTContext &Ctx, + const UnsafeBufferUsageHandler &Handler) = 0; + virtual ~FastMatcher() = default; +}; + +class MatchResult { + +public: + template const T *getNodeAs(StringRef ID) const { +auto It = Nodes.find(std::string(ID)); +if (It == Nodes.end()) { + return nullptr; +} +return It->second.get(); + } + + void addNode(StringRef ID, const DynTypedNode &Node) { +Nodes[std::string(ID)] = Node; + } + +private: + llvm::StringMap Nodes; +}; +} // namespace + // A `RecursiveASTVisitor` that traverses all descendants of a given node "n" // except for those belonging to a different callable of "n". class MatchDescendantVisitor : public DynamicRecursiveASTVisitor { @@ -87,13 +118,11 @@ class MatchDescendantVisitor : public DynamicRecursiveASTVisitor { // Creates an AST visitor that matches `Matcher` on all // descendants of a given node "n" except for the ones // belonging to a different callable of "n". - MatchDescendantVisitor(const internal::DynTypedMatcher *Matcher, - internal::ASTMatchFinder *Finder, - internal::BoundNodesTreeBuilder *Builder, - internal::ASTMatchFinder::BindKind Bind, + MatchDescendantVisitor(FastMatcher &Matcher, bool FindAll, const bool ignoreUnevaluatedContext) - : Matcher(Matcher), Finder(Finder), Builder(Builder), Bind(Bind), -Matches(false), ignoreUnevaluatedContext(ignoreUnevaluatedContext) { + : Matcher(&Matcher), FindAll(FindAll), Matches(false), +ignoreUnevaluatedContext(ignoreUnevaluatedContext), +ActiveASTContext(nullptr), Handler(nullptr) { ShouldVisitTemplateInstantiations = true; ShouldVisitImplicitCode = false; // TODO: let's ignore implicit code for now } @@ -104,7 +133,6 @@ class MatchDescendantVisitor : public DynamicRecursiveASTVisitor { Matches = false; if (const Stmt *StmtNode = DynNode.get()) { TraverseStmt(const_cast(StmtNode)); - *Builder = ResultBindings; return Matches; } return false; @@ -186,106 +214,212 @@ class MatchDescendantVisitor : public DynamicRecursiveASTVisitor { return DynamicRecursiveASTVisitor::TraverseStmt(Node); } + void setASTContext(ASTContext &Context) { ActiveASTContext = &Context; } + + void setHandler(const UnsafeBufferUsageHandler &NewHandler) { +Handler = &NewHandler; + } + private: // Sets 'Matched' to true if 'Matcher' matches 'Node' // // Returns 'true' if traversal should continue after this function // returns, i.e. if no match is found or 'Bind'
[clang] [Clang] Optimize -Wunsafe-buffer-usage. (PR #125492)
ivanaivanovska wrote: > @ivanaivanovska @ilya-biryukov One PR is fine. I will look at it. @ziqingluo-90 Thank you! https://github.com/llvm/llvm-project/pull/125492 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Optimize -Wunsafe-buffer-usage. (PR #124554)
https://github.com/ivanaivanovska updated https://github.com/llvm/llvm-project/pull/124554 504 Gateway Time-out The server didn't respond in time. ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Optimize -Wunsafe-buffer-usage. (PR #125492)
@@ -186,106 +212,208 @@ class MatchDescendantVisitor : public DynamicRecursiveASTVisitor { return DynamicRecursiveASTVisitor::TraverseStmt(Node); } + void setASTContext(ASTContext &Context) { ActiveASTContext = &Context; } + + void setHandler(const UnsafeBufferUsageHandler &NewHandler) { +Handler = &NewHandler; + } + private: // Sets 'Matched' to true if 'Matcher' matches 'Node' // // Returns 'true' if traversal should continue after this function // returns, i.e. if no match is found or 'Bind' is 'BK_All'. template bool match(const T &Node) { -internal::BoundNodesTreeBuilder RecursiveBuilder(*Builder); - -if (Matcher->matches(DynTypedNode::create(Node), Finder, - &RecursiveBuilder)) { - ResultBindings.addMatch(RecursiveBuilder); +if (Matcher->matches(DynTypedNode::create(Node), *ActiveASTContext, + *Handler)) { Matches = true; - if (Bind != internal::ASTMatchFinder::BK_All) + if (!FindAll) return false; // Abort as soon as a match is found. } return true; } - const internal::DynTypedMatcher *const Matcher; - internal::ASTMatchFinder *const Finder; - internal::BoundNodesTreeBuilder *const Builder; - internal::BoundNodesTreeBuilder ResultBindings; - const internal::ASTMatchFinder::BindKind Bind; + FastMatcher *const Matcher; + // When true, finds all matches. When false, finds the first match and stops. + const bool FindAll; bool Matches; bool ignoreUnevaluatedContext; + ASTContext *ActiveASTContext; + const UnsafeBufferUsageHandler *Handler; }; // Because we're dealing with raw pointers, let's define what we mean by that. -static auto hasPointerType() { - return hasType(hasCanonicalType(pointerType())); +static bool hasPointerType(const Expr &E) { + return isa(E.getType().getCanonicalType()); } -static auto hasArrayType() { return hasType(hasCanonicalType(arrayType())); } - -AST_MATCHER_P(Stmt, forEachDescendantEvaluatedStmt, internal::Matcher, - innerMatcher) { - const DynTypedMatcher &DTM = static_cast(innerMatcher); - - MatchDescendantVisitor Visitor(&DTM, Finder, Builder, ASTMatchFinder::BK_All, - true); - return Visitor.findMatch(DynTypedNode::create(Node)); +static bool hasArrayType(const Expr &E) { + return isa(E.getType().getCanonicalType()); } -AST_MATCHER_P(Stmt, forEachDescendantStmt, internal::Matcher, - innerMatcher) { - const DynTypedMatcher &DTM = static_cast(innerMatcher); +static void +forEachDescendantEvaluatedStmt(const Stmt *S, ASTContext &Ctx, + const UnsafeBufferUsageHandler &Handler, + FastMatcher &Matcher) { + MatchDescendantVisitor Visitor(Matcher, /*FindAll=*/true, + /*ignoreUnevaluatedContext=*/true); + Visitor.setASTContext(Ctx); + Visitor.setHandler(Handler); + Visitor.findMatch(DynTypedNode::create(*S)); +} - MatchDescendantVisitor Visitor(&DTM, Finder, Builder, ASTMatchFinder::BK_All, - false); - return Visitor.findMatch(DynTypedNode::create(Node)); +static void forEachDescendantStmt(const Stmt *S, ASTContext &Ctx, + const UnsafeBufferUsageHandler &Handler, + FastMatcher &Matcher) { + MatchDescendantVisitor Visitor(Matcher, /*FindAll=*/true, + /*ignoreUnevaluatedContext=*/false); + Visitor.setASTContext(Ctx); + Visitor.setHandler(Handler); + Visitor.findMatch(DynTypedNode::create(*S)); } // Matches a `Stmt` node iff the node is in a safe-buffer opt-out region -AST_MATCHER_P(Stmt, notInSafeBufferOptOut, const UnsafeBufferUsageHandler *, - Handler) { +static bool notInSafeBufferOptOut(const Stmt &Node, + const UnsafeBufferUsageHandler *Handler) { return !Handler->isSafeBufferOptOut(Node.getBeginLoc()); } -AST_MATCHER_P(Stmt, ignoreUnsafeBufferInContainer, - const UnsafeBufferUsageHandler *, Handler) { +static bool +ignoreUnsafeBufferInContainer(const Stmt &Node, + const UnsafeBufferUsageHandler *Handler) { return Handler->ignoreUnsafeBufferInContainer(Node.getBeginLoc()); } -AST_MATCHER_P(Stmt, ignoreUnsafeLibcCall, const UnsafeBufferUsageHandler *, - Handler) { - if (Finder->getASTContext().getLangOpts().CPlusPlus) +static bool ignoreUnsafeLibcCall(const ASTContext &Ctx, const Stmt &Node, + const UnsafeBufferUsageHandler *Handler) { + if (Ctx.getLangOpts().CPlusPlus) return Handler->ignoreUnsafeBufferInLibcCall(Node.getBeginLoc()); return true; /* Only warn about libc calls for C++ */ } -AST_MATCHER_P(CastExpr, castSubExpr, internal::Matcher, innerMatcher) { - return innerMatcher.matches(*Node.getSubExpr(), Finder, Builder); +// Finds any exp
[clang] [Clang] Optimize -Wunsafe-buffer-usage. (PR #125492)
@@ -186,106 +212,208 @@ class MatchDescendantVisitor : public DynamicRecursiveASTVisitor { return DynamicRecursiveASTVisitor::TraverseStmt(Node); } + void setASTContext(ASTContext &Context) { ActiveASTContext = &Context; } + + void setHandler(const UnsafeBufferUsageHandler &NewHandler) { +Handler = &NewHandler; + } + private: // Sets 'Matched' to true if 'Matcher' matches 'Node' // // Returns 'true' if traversal should continue after this function // returns, i.e. if no match is found or 'Bind' is 'BK_All'. template bool match(const T &Node) { -internal::BoundNodesTreeBuilder RecursiveBuilder(*Builder); - -if (Matcher->matches(DynTypedNode::create(Node), Finder, - &RecursiveBuilder)) { - ResultBindings.addMatch(RecursiveBuilder); +if (Matcher->matches(DynTypedNode::create(Node), *ActiveASTContext, + *Handler)) { Matches = true; - if (Bind != internal::ASTMatchFinder::BK_All) + if (!FindAll) return false; // Abort as soon as a match is found. } return true; } - const internal::DynTypedMatcher *const Matcher; - internal::ASTMatchFinder *const Finder; - internal::BoundNodesTreeBuilder *const Builder; - internal::BoundNodesTreeBuilder ResultBindings; - const internal::ASTMatchFinder::BindKind Bind; + FastMatcher *const Matcher; + // When true, finds all matches. When false, finds the first match and stops. + const bool FindAll; bool Matches; bool ignoreUnevaluatedContext; + ASTContext *ActiveASTContext; + const UnsafeBufferUsageHandler *Handler; }; // Because we're dealing with raw pointers, let's define what we mean by that. -static auto hasPointerType() { - return hasType(hasCanonicalType(pointerType())); +static bool hasPointerType(const Expr &E) { + return isa(E.getType().getCanonicalType()); } -static auto hasArrayType() { return hasType(hasCanonicalType(arrayType())); } - -AST_MATCHER_P(Stmt, forEachDescendantEvaluatedStmt, internal::Matcher, - innerMatcher) { - const DynTypedMatcher &DTM = static_cast(innerMatcher); - - MatchDescendantVisitor Visitor(&DTM, Finder, Builder, ASTMatchFinder::BK_All, - true); - return Visitor.findMatch(DynTypedNode::create(Node)); +static bool hasArrayType(const Expr &E) { + return isa(E.getType().getCanonicalType()); } -AST_MATCHER_P(Stmt, forEachDescendantStmt, internal::Matcher, - innerMatcher) { - const DynTypedMatcher &DTM = static_cast(innerMatcher); +static void +forEachDescendantEvaluatedStmt(const Stmt *S, ASTContext &Ctx, + const UnsafeBufferUsageHandler &Handler, + FastMatcher &Matcher) { + MatchDescendantVisitor Visitor(Matcher, /*FindAll=*/true, + /*ignoreUnevaluatedContext=*/true); + Visitor.setASTContext(Ctx); + Visitor.setHandler(Handler); + Visitor.findMatch(DynTypedNode::create(*S)); +} - MatchDescendantVisitor Visitor(&DTM, Finder, Builder, ASTMatchFinder::BK_All, - false); - return Visitor.findMatch(DynTypedNode::create(Node)); +static void forEachDescendantStmt(const Stmt *S, ASTContext &Ctx, + const UnsafeBufferUsageHandler &Handler, + FastMatcher &Matcher) { + MatchDescendantVisitor Visitor(Matcher, /*FindAll=*/true, + /*ignoreUnevaluatedContext=*/false); + Visitor.setASTContext(Ctx); + Visitor.setHandler(Handler); + Visitor.findMatch(DynTypedNode::create(*S)); } // Matches a `Stmt` node iff the node is in a safe-buffer opt-out region -AST_MATCHER_P(Stmt, notInSafeBufferOptOut, const UnsafeBufferUsageHandler *, - Handler) { +static bool notInSafeBufferOptOut(const Stmt &Node, + const UnsafeBufferUsageHandler *Handler) { return !Handler->isSafeBufferOptOut(Node.getBeginLoc()); } -AST_MATCHER_P(Stmt, ignoreUnsafeBufferInContainer, - const UnsafeBufferUsageHandler *, Handler) { +static bool +ignoreUnsafeBufferInContainer(const Stmt &Node, + const UnsafeBufferUsageHandler *Handler) { return Handler->ignoreUnsafeBufferInContainer(Node.getBeginLoc()); } -AST_MATCHER_P(Stmt, ignoreUnsafeLibcCall, const UnsafeBufferUsageHandler *, - Handler) { - if (Finder->getASTContext().getLangOpts().CPlusPlus) +static bool ignoreUnsafeLibcCall(const ASTContext &Ctx, const Stmt &Node, + const UnsafeBufferUsageHandler *Handler) { + if (Ctx.getLangOpts().CPlusPlus) return Handler->ignoreUnsafeBufferInLibcCall(Node.getBeginLoc()); return true; /* Only warn about libc calls for C++ */ } -AST_MATCHER_P(CastExpr, castSubExpr, internal::Matcher, innerMatcher) { - return innerMatcher.matches(*Node.getSubExpr(), Finder, Builder); +// Finds any exp
[clang] [Clang] Optimize -Wunsafe-buffer-usage. (PR #125492)
@@ -186,106 +212,208 @@ class MatchDescendantVisitor : public DynamicRecursiveASTVisitor { return DynamicRecursiveASTVisitor::TraverseStmt(Node); } + void setASTContext(ASTContext &Context) { ActiveASTContext = &Context; } + + void setHandler(const UnsafeBufferUsageHandler &NewHandler) { +Handler = &NewHandler; + } + private: // Sets 'Matched' to true if 'Matcher' matches 'Node' // // Returns 'true' if traversal should continue after this function // returns, i.e. if no match is found or 'Bind' is 'BK_All'. template bool match(const T &Node) { -internal::BoundNodesTreeBuilder RecursiveBuilder(*Builder); - -if (Matcher->matches(DynTypedNode::create(Node), Finder, - &RecursiveBuilder)) { - ResultBindings.addMatch(RecursiveBuilder); +if (Matcher->matches(DynTypedNode::create(Node), *ActiveASTContext, + *Handler)) { Matches = true; - if (Bind != internal::ASTMatchFinder::BK_All) + if (!FindAll) return false; // Abort as soon as a match is found. } return true; } - const internal::DynTypedMatcher *const Matcher; - internal::ASTMatchFinder *const Finder; - internal::BoundNodesTreeBuilder *const Builder; - internal::BoundNodesTreeBuilder ResultBindings; - const internal::ASTMatchFinder::BindKind Bind; + FastMatcher *const Matcher; + // When true, finds all matches. When false, finds the first match and stops. + const bool FindAll; bool Matches; bool ignoreUnevaluatedContext; + ASTContext *ActiveASTContext; + const UnsafeBufferUsageHandler *Handler; }; // Because we're dealing with raw pointers, let's define what we mean by that. -static auto hasPointerType() { - return hasType(hasCanonicalType(pointerType())); +static bool hasPointerType(const Expr &E) { + return isa(E.getType().getCanonicalType()); } -static auto hasArrayType() { return hasType(hasCanonicalType(arrayType())); } - -AST_MATCHER_P(Stmt, forEachDescendantEvaluatedStmt, internal::Matcher, - innerMatcher) { - const DynTypedMatcher &DTM = static_cast(innerMatcher); - - MatchDescendantVisitor Visitor(&DTM, Finder, Builder, ASTMatchFinder::BK_All, - true); - return Visitor.findMatch(DynTypedNode::create(Node)); +static bool hasArrayType(const Expr &E) { + return isa(E.getType().getCanonicalType()); } -AST_MATCHER_P(Stmt, forEachDescendantStmt, internal::Matcher, - innerMatcher) { - const DynTypedMatcher &DTM = static_cast(innerMatcher); +static void +forEachDescendantEvaluatedStmt(const Stmt *S, ASTContext &Ctx, + const UnsafeBufferUsageHandler &Handler, + FastMatcher &Matcher) { + MatchDescendantVisitor Visitor(Matcher, /*FindAll=*/true, + /*ignoreUnevaluatedContext=*/true); + Visitor.setASTContext(Ctx); + Visitor.setHandler(Handler); + Visitor.findMatch(DynTypedNode::create(*S)); +} - MatchDescendantVisitor Visitor(&DTM, Finder, Builder, ASTMatchFinder::BK_All, - false); - return Visitor.findMatch(DynTypedNode::create(Node)); +static void forEachDescendantStmt(const Stmt *S, ASTContext &Ctx, + const UnsafeBufferUsageHandler &Handler, + FastMatcher &Matcher) { + MatchDescendantVisitor Visitor(Matcher, /*FindAll=*/true, + /*ignoreUnevaluatedContext=*/false); + Visitor.setASTContext(Ctx); + Visitor.setHandler(Handler); + Visitor.findMatch(DynTypedNode::create(*S)); } // Matches a `Stmt` node iff the node is in a safe-buffer opt-out region -AST_MATCHER_P(Stmt, notInSafeBufferOptOut, const UnsafeBufferUsageHandler *, - Handler) { +static bool notInSafeBufferOptOut(const Stmt &Node, + const UnsafeBufferUsageHandler *Handler) { return !Handler->isSafeBufferOptOut(Node.getBeginLoc()); } -AST_MATCHER_P(Stmt, ignoreUnsafeBufferInContainer, - const UnsafeBufferUsageHandler *, Handler) { +static bool +ignoreUnsafeBufferInContainer(const Stmt &Node, + const UnsafeBufferUsageHandler *Handler) { return Handler->ignoreUnsafeBufferInContainer(Node.getBeginLoc()); } -AST_MATCHER_P(Stmt, ignoreUnsafeLibcCall, const UnsafeBufferUsageHandler *, - Handler) { - if (Finder->getASTContext().getLangOpts().CPlusPlus) +static bool ignoreUnsafeLibcCall(const ASTContext &Ctx, const Stmt &Node, + const UnsafeBufferUsageHandler *Handler) { + if (Ctx.getLangOpts().CPlusPlus) return Handler->ignoreUnsafeBufferInLibcCall(Node.getBeginLoc()); return true; /* Only warn about libc calls for C++ */ } -AST_MATCHER_P(CastExpr, castSubExpr, internal::Matcher, innerMatcher) { - return innerMatcher.matches(*Node.getSubExpr(), Finder, Builder); +// Finds any exp
[clang] [Clang] Optimize -Wunsafe-buffer-usage. (PR #125492)
@@ -186,106 +212,208 @@ class MatchDescendantVisitor : public DynamicRecursiveASTVisitor { return DynamicRecursiveASTVisitor::TraverseStmt(Node); } + void setASTContext(ASTContext &Context) { ActiveASTContext = &Context; } + + void setHandler(const UnsafeBufferUsageHandler &NewHandler) { +Handler = &NewHandler; + } + private: // Sets 'Matched' to true if 'Matcher' matches 'Node' // // Returns 'true' if traversal should continue after this function // returns, i.e. if no match is found or 'Bind' is 'BK_All'. template bool match(const T &Node) { -internal::BoundNodesTreeBuilder RecursiveBuilder(*Builder); - -if (Matcher->matches(DynTypedNode::create(Node), Finder, - &RecursiveBuilder)) { - ResultBindings.addMatch(RecursiveBuilder); +if (Matcher->matches(DynTypedNode::create(Node), *ActiveASTContext, + *Handler)) { Matches = true; - if (Bind != internal::ASTMatchFinder::BK_All) + if (!FindAll) return false; // Abort as soon as a match is found. } return true; } - const internal::DynTypedMatcher *const Matcher; - internal::ASTMatchFinder *const Finder; - internal::BoundNodesTreeBuilder *const Builder; - internal::BoundNodesTreeBuilder ResultBindings; - const internal::ASTMatchFinder::BindKind Bind; + FastMatcher *const Matcher; + // When true, finds all matches. When false, finds the first match and stops. + const bool FindAll; bool Matches; bool ignoreUnevaluatedContext; + ASTContext *ActiveASTContext; + const UnsafeBufferUsageHandler *Handler; }; // Because we're dealing with raw pointers, let's define what we mean by that. -static auto hasPointerType() { - return hasType(hasCanonicalType(pointerType())); +static bool hasPointerType(const Expr &E) { + return isa(E.getType().getCanonicalType()); } -static auto hasArrayType() { return hasType(hasCanonicalType(arrayType())); } - -AST_MATCHER_P(Stmt, forEachDescendantEvaluatedStmt, internal::Matcher, - innerMatcher) { - const DynTypedMatcher &DTM = static_cast(innerMatcher); - - MatchDescendantVisitor Visitor(&DTM, Finder, Builder, ASTMatchFinder::BK_All, - true); - return Visitor.findMatch(DynTypedNode::create(Node)); +static bool hasArrayType(const Expr &E) { + return isa(E.getType().getCanonicalType()); } -AST_MATCHER_P(Stmt, forEachDescendantStmt, internal::Matcher, - innerMatcher) { - const DynTypedMatcher &DTM = static_cast(innerMatcher); +static void +forEachDescendantEvaluatedStmt(const Stmt *S, ASTContext &Ctx, + const UnsafeBufferUsageHandler &Handler, + FastMatcher &Matcher) { + MatchDescendantVisitor Visitor(Matcher, /*FindAll=*/true, + /*ignoreUnevaluatedContext=*/true); + Visitor.setASTContext(Ctx); + Visitor.setHandler(Handler); + Visitor.findMatch(DynTypedNode::create(*S)); +} - MatchDescendantVisitor Visitor(&DTM, Finder, Builder, ASTMatchFinder::BK_All, - false); - return Visitor.findMatch(DynTypedNode::create(Node)); +static void forEachDescendantStmt(const Stmt *S, ASTContext &Ctx, + const UnsafeBufferUsageHandler &Handler, + FastMatcher &Matcher) { + MatchDescendantVisitor Visitor(Matcher, /*FindAll=*/true, + /*ignoreUnevaluatedContext=*/false); + Visitor.setASTContext(Ctx); + Visitor.setHandler(Handler); + Visitor.findMatch(DynTypedNode::create(*S)); } // Matches a `Stmt` node iff the node is in a safe-buffer opt-out region -AST_MATCHER_P(Stmt, notInSafeBufferOptOut, const UnsafeBufferUsageHandler *, - Handler) { +static bool notInSafeBufferOptOut(const Stmt &Node, + const UnsafeBufferUsageHandler *Handler) { return !Handler->isSafeBufferOptOut(Node.getBeginLoc()); } -AST_MATCHER_P(Stmt, ignoreUnsafeBufferInContainer, - const UnsafeBufferUsageHandler *, Handler) { +static bool +ignoreUnsafeBufferInContainer(const Stmt &Node, + const UnsafeBufferUsageHandler *Handler) { return Handler->ignoreUnsafeBufferInContainer(Node.getBeginLoc()); } -AST_MATCHER_P(Stmt, ignoreUnsafeLibcCall, const UnsafeBufferUsageHandler *, - Handler) { - if (Finder->getASTContext().getLangOpts().CPlusPlus) +static bool ignoreUnsafeLibcCall(const ASTContext &Ctx, const Stmt &Node, + const UnsafeBufferUsageHandler *Handler) { + if (Ctx.getLangOpts().CPlusPlus) return Handler->ignoreUnsafeBufferInLibcCall(Node.getBeginLoc()); return true; /* Only warn about libc calls for C++ */ } -AST_MATCHER_P(CastExpr, castSubExpr, internal::Matcher, innerMatcher) { - return innerMatcher.matches(*Node.getSubExpr(), Finder, Builder); +// Finds any exp
[clang] [Clang] Optimize -Wunsafe-buffer-usage. (PR #125492)
@@ -1561,56 +1821,70 @@ class UnsafeLibcFunctionCallGadget : public WarningGadget { } WarnedFunKind = OTHERS; public: - UnsafeLibcFunctionCallGadget(const MatchFinder::MatchResult &Result) + UnsafeLibcFunctionCallGadget(const MatchResult &Result) : WarningGadget(Kind::UnsafeLibcFunctionCall), -Call(Result.Nodes.getNodeAs(Tag)) { -if (Result.Nodes.getNodeAs(UnsafeSprintfTag)) +Call(Result.getNodeAs(Tag)) { +if (Result.getNodeAs(UnsafeSprintfTag)) WarnedFunKind = SPRINTF; -else if (auto *E = Result.Nodes.getNodeAs(UnsafeStringTag)) { +else if (auto *E = Result.getNodeAs(UnsafeStringTag)) { WarnedFunKind = STRING; UnsafeArg = E; -} else if (Result.Nodes.getNodeAs(UnsafeSizedByTag)) { +} else if (Result.getNodeAs(UnsafeSizedByTag)) { WarnedFunKind = SIZED_BY; UnsafeArg = Call->getArg(0); -} else if (Result.Nodes.getNodeAs(UnsafeVaListTag)) +} else if (Result.getNodeAs(UnsafeVaListTag)) WarnedFunKind = VA_LIST; } - static Matcher matcher(const UnsafeBufferUsageHandler *Handler) { -return stmt(unless(ignoreUnsafeLibcCall(Handler)), - anyOf( -callExpr( -callee(functionDecl(anyOf( -// Match a predefined unsafe libc -// function: -functionDecl(libc_func_matchers::isPredefinedUnsafeLibcFunc()), -// Match a call to one of the `v*printf` functions -// taking va-list, which cannot be checked at -// compile-time: -functionDecl(libc_func_matchers::isUnsafeVaListPrintfFunc()) -.bind(UnsafeVaListTag), -// Match a call to a `sprintf` function, which is never -// safe: -functionDecl(libc_func_matchers::isUnsafeSprintfFunc()) -.bind(UnsafeSprintfTag, -// (unless the call has a sole string literal argument): -unless( -allOf(hasArgument(0, expr(stringLiteral())), hasNumArgs(1, - -// The following two cases require checking against actual -// arguments of the call: - -// Match a call to an `snprintf` function. And first two -// arguments of the call (that describe a buffer) are not in -// safe patterns: - callExpr(callee(functionDecl(libc_func_matchers::isNormalPrintfFunc())), - libc_func_matchers::hasUnsafeSnprintfBuffer()) -.bind(UnsafeSizedByTag), -// Match a call to a `printf` function, which can be safe if -// all arguments are null-terminated: - callExpr(callee(functionDecl(libc_func_matchers::isNormalPrintfFunc())), - libc_func_matchers::hasUnsafePrintfStringArg( - expr().bind(UnsafeStringTag); + static bool matches(const Stmt *S, ASTContext &Ctx, + const UnsafeBufferUsageHandler *Handler, + MatchResult &Result) { +if (ignoreUnsafeLibcCall(Ctx, *S, Handler)) + return false; +auto *CE = dyn_cast(S); +if (!CE || !CE->getDirectCallee()) + return false; +const auto *FD = dyn_cast(CE->getDirectCallee()); +if (!FD) + return false; +auto isSingleStringLiteralArg = false; +if (CE->getNumArgs() == 1) { + const auto *const Arg = CE->getArg(0); + if (isa(Arg) && !Arg->children().empty()) { +isSingleStringLiteralArg = +isa(*Arg->children().begin()); + } +} +if (!isSingleStringLiteralArg) { // (unless the call has a sole string ivanaivanovska wrote: Done. https://github.com/llvm/llvm-project/pull/125492 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Optimize -Wunsafe-buffer-usage. (PR #125492)
@@ -1561,56 +1821,70 @@ class UnsafeLibcFunctionCallGadget : public WarningGadget { } WarnedFunKind = OTHERS; public: - UnsafeLibcFunctionCallGadget(const MatchFinder::MatchResult &Result) + UnsafeLibcFunctionCallGadget(const MatchResult &Result) : WarningGadget(Kind::UnsafeLibcFunctionCall), -Call(Result.Nodes.getNodeAs(Tag)) { -if (Result.Nodes.getNodeAs(UnsafeSprintfTag)) +Call(Result.getNodeAs(Tag)) { +if (Result.getNodeAs(UnsafeSprintfTag)) WarnedFunKind = SPRINTF; -else if (auto *E = Result.Nodes.getNodeAs(UnsafeStringTag)) { +else if (auto *E = Result.getNodeAs(UnsafeStringTag)) { WarnedFunKind = STRING; UnsafeArg = E; -} else if (Result.Nodes.getNodeAs(UnsafeSizedByTag)) { +} else if (Result.getNodeAs(UnsafeSizedByTag)) { WarnedFunKind = SIZED_BY; UnsafeArg = Call->getArg(0); -} else if (Result.Nodes.getNodeAs(UnsafeVaListTag)) +} else if (Result.getNodeAs(UnsafeVaListTag)) WarnedFunKind = VA_LIST; } - static Matcher matcher(const UnsafeBufferUsageHandler *Handler) { -return stmt(unless(ignoreUnsafeLibcCall(Handler)), - anyOf( -callExpr( -callee(functionDecl(anyOf( -// Match a predefined unsafe libc -// function: -functionDecl(libc_func_matchers::isPredefinedUnsafeLibcFunc()), -// Match a call to one of the `v*printf` functions -// taking va-list, which cannot be checked at -// compile-time: -functionDecl(libc_func_matchers::isUnsafeVaListPrintfFunc()) -.bind(UnsafeVaListTag), -// Match a call to a `sprintf` function, which is never -// safe: -functionDecl(libc_func_matchers::isUnsafeSprintfFunc()) -.bind(UnsafeSprintfTag, -// (unless the call has a sole string literal argument): -unless( -allOf(hasArgument(0, expr(stringLiteral())), hasNumArgs(1, - -// The following two cases require checking against actual -// arguments of the call: - -// Match a call to an `snprintf` function. And first two -// arguments of the call (that describe a buffer) are not in -// safe patterns: - callExpr(callee(functionDecl(libc_func_matchers::isNormalPrintfFunc())), - libc_func_matchers::hasUnsafeSnprintfBuffer()) -.bind(UnsafeSizedByTag), -// Match a call to a `printf` function, which can be safe if -// all arguments are null-terminated: - callExpr(callee(functionDecl(libc_func_matchers::isNormalPrintfFunc())), - libc_func_matchers::hasUnsafePrintfStringArg( - expr().bind(UnsafeStringTag); + static bool matches(const Stmt *S, ASTContext &Ctx, + const UnsafeBufferUsageHandler *Handler, + MatchResult &Result) { +if (ignoreUnsafeLibcCall(Ctx, *S, Handler)) + return false; +auto *CE = dyn_cast(S); +if (!CE || !CE->getDirectCallee()) + return false; +const auto *FD = dyn_cast(CE->getDirectCallee()); +if (!FD) + return false; +auto isSingleStringLiteralArg = false; +if (CE->getNumArgs() == 1) { + const auto *const Arg = CE->getArg(0); + if (isa(Arg) && !Arg->children().empty()) { +isSingleStringLiteralArg = +isa(*Arg->children().begin()); ivanaivanovska wrote: Fixed. https://github.com/llvm/llvm-project/pull/125492 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Optimize -Wunsafe-buffer-usage. (PR #125492)
@@ -1561,56 +1821,70 @@ class UnsafeLibcFunctionCallGadget : public WarningGadget { } WarnedFunKind = OTHERS; public: - UnsafeLibcFunctionCallGadget(const MatchFinder::MatchResult &Result) + UnsafeLibcFunctionCallGadget(const MatchResult &Result) : WarningGadget(Kind::UnsafeLibcFunctionCall), -Call(Result.Nodes.getNodeAs(Tag)) { -if (Result.Nodes.getNodeAs(UnsafeSprintfTag)) +Call(Result.getNodeAs(Tag)) { +if (Result.getNodeAs(UnsafeSprintfTag)) WarnedFunKind = SPRINTF; -else if (auto *E = Result.Nodes.getNodeAs(UnsafeStringTag)) { +else if (auto *E = Result.getNodeAs(UnsafeStringTag)) { WarnedFunKind = STRING; UnsafeArg = E; -} else if (Result.Nodes.getNodeAs(UnsafeSizedByTag)) { +} else if (Result.getNodeAs(UnsafeSizedByTag)) { WarnedFunKind = SIZED_BY; UnsafeArg = Call->getArg(0); -} else if (Result.Nodes.getNodeAs(UnsafeVaListTag)) +} else if (Result.getNodeAs(UnsafeVaListTag)) WarnedFunKind = VA_LIST; } - static Matcher matcher(const UnsafeBufferUsageHandler *Handler) { -return stmt(unless(ignoreUnsafeLibcCall(Handler)), - anyOf( -callExpr( -callee(functionDecl(anyOf( -// Match a predefined unsafe libc -// function: -functionDecl(libc_func_matchers::isPredefinedUnsafeLibcFunc()), -// Match a call to one of the `v*printf` functions -// taking va-list, which cannot be checked at -// compile-time: -functionDecl(libc_func_matchers::isUnsafeVaListPrintfFunc()) -.bind(UnsafeVaListTag), -// Match a call to a `sprintf` function, which is never -// safe: -functionDecl(libc_func_matchers::isUnsafeSprintfFunc()) -.bind(UnsafeSprintfTag, -// (unless the call has a sole string literal argument): -unless( -allOf(hasArgument(0, expr(stringLiteral())), hasNumArgs(1, - -// The following two cases require checking against actual -// arguments of the call: - -// Match a call to an `snprintf` function. And first two -// arguments of the call (that describe a buffer) are not in -// safe patterns: - callExpr(callee(functionDecl(libc_func_matchers::isNormalPrintfFunc())), - libc_func_matchers::hasUnsafeSnprintfBuffer()) -.bind(UnsafeSizedByTag), -// Match a call to a `printf` function, which can be safe if -// all arguments are null-terminated: - callExpr(callee(functionDecl(libc_func_matchers::isNormalPrintfFunc())), - libc_func_matchers::hasUnsafePrintfStringArg( - expr().bind(UnsafeStringTag); + static bool matches(const Stmt *S, ASTContext &Ctx, + const UnsafeBufferUsageHandler *Handler, + MatchResult &Result) { +if (ignoreUnsafeLibcCall(Ctx, *S, Handler)) + return false; +auto *CE = dyn_cast(S); +if (!CE || !CE->getDirectCallee()) + return false; +const auto *FD = dyn_cast(CE->getDirectCallee()); +if (!FD) + return false; +auto isSingleStringLiteralArg = false; +if (CE->getNumArgs() == 1) { + const auto *const Arg = CE->getArg(0); + if (isa(Arg) && !Arg->children().empty()) { ivanaivanovska wrote: Done. https://github.com/llvm/llvm-project/pull/125492 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Optimize -Wunsafe-buffer-usage. (PR #125492)
@@ -1139,26 +1276,30 @@ class ArraySubscriptGadget : public WarningGadget { const ArraySubscriptExpr *ASE; public: - ArraySubscriptGadget(const MatchFinder::MatchResult &Result) + ArraySubscriptGadget(const MatchResult &Result) : WarningGadget(Kind::ArraySubscript), -ASE(Result.Nodes.getNodeAs(ArraySubscrTag)) {} +ASE(Result.getNodeAs(ArraySubscrTag)) {} static bool classof(const Gadget *G) { return G->getKind() == Kind::ArraySubscript; } - static Matcher matcher() { -// clang-format off - return stmt(arraySubscriptExpr( -hasBase(ignoringParenImpCasts( - anyOf(hasPointerType(), hasArrayType(, -unless(anyOf( - isSafeArraySubscript(), - hasIndex( - anyOf(integerLiteral(equals(0)), arrayInitIndexExpr()) - ) -))).bind(ArraySubscrTag)); -// clang-format on + static bool matches(const Stmt *S, const ASTContext &Ctx, + MatchResult &Result) { +const auto *ASE = dyn_cast(S); +if (!ASE) + return false; +const auto *const Base = ASE->getBase()->IgnoreParenImpCasts(); +if (!hasPointerType(*Base) && !hasArrayType(*Base)) + return false; +bool IsSafeIndex = +(isa(ASE->getIdx()) && + cast(ASE->getIdx())->getValue().isZero()) || +isa(ASE->getIdx()); +if (isSafeArraySubscript(*ASE, Ctx) || IsSafeIndex) ivanaivanovska wrote: Done. https://github.com/llvm/llvm-project/pull/125492 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Optimize -Wunsafe-buffer-usage. (PR #125492)
@@ -1139,26 +1276,30 @@ class ArraySubscriptGadget : public WarningGadget { const ArraySubscriptExpr *ASE; public: - ArraySubscriptGadget(const MatchFinder::MatchResult &Result) + ArraySubscriptGadget(const MatchResult &Result) : WarningGadget(Kind::ArraySubscript), -ASE(Result.Nodes.getNodeAs(ArraySubscrTag)) {} +ASE(Result.getNodeAs(ArraySubscrTag)) {} static bool classof(const Gadget *G) { return G->getKind() == Kind::ArraySubscript; } - static Matcher matcher() { -// clang-format off - return stmt(arraySubscriptExpr( -hasBase(ignoringParenImpCasts( - anyOf(hasPointerType(), hasArrayType(, -unless(anyOf( - isSafeArraySubscript(), - hasIndex( - anyOf(integerLiteral(equals(0)), arrayInitIndexExpr()) - ) -))).bind(ArraySubscrTag)); -// clang-format on + static bool matches(const Stmt *S, const ASTContext &Ctx, + MatchResult &Result) { +const auto *ASE = dyn_cast(S); +if (!ASE) + return false; +const auto *const Base = ASE->getBase()->IgnoreParenImpCasts(); +if (!hasPointerType(*Base) && !hasArrayType(*Base)) + return false; +bool IsSafeIndex = +(isa(ASE->getIdx()) && ivanaivanovska wrote: Done. https://github.com/llvm/llvm-project/pull/125492 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Optimize -Wunsafe-buffer-usage. (PR #125492)
@@ -186,106 +212,193 @@ class MatchDescendantVisitor : public DynamicRecursiveASTVisitor { return DynamicRecursiveASTVisitor::TraverseStmt(Node); } + void setASTContext(ASTContext &Context) { ActiveASTContext = &Context; } + + void setHandler(const UnsafeBufferUsageHandler &NewHandler) { +Handler = &NewHandler; + } + private: // Sets 'Matched' to true if 'Matcher' matches 'Node' // // Returns 'true' if traversal should continue after this function // returns, i.e. if no match is found or 'Bind' is 'BK_All'. template bool match(const T &Node) { -internal::BoundNodesTreeBuilder RecursiveBuilder(*Builder); - -if (Matcher->matches(DynTypedNode::create(Node), Finder, - &RecursiveBuilder)) { - ResultBindings.addMatch(RecursiveBuilder); +if (Matcher->matches(DynTypedNode::create(Node), *ActiveASTContext, + *Handler)) { Matches = true; - if (Bind != internal::ASTMatchFinder::BK_All) + if (!FindAll) return false; // Abort as soon as a match is found. } return true; } - const internal::DynTypedMatcher *const Matcher; - internal::ASTMatchFinder *const Finder; - internal::BoundNodesTreeBuilder *const Builder; - internal::BoundNodesTreeBuilder ResultBindings; - const internal::ASTMatchFinder::BindKind Bind; + FastMatcher *const Matcher; + // When true, finds all matches. When false, finds the first match and stops. + const bool FindAll; bool Matches; bool ignoreUnevaluatedContext; + ASTContext *ActiveASTContext; + const UnsafeBufferUsageHandler *Handler; }; // Because we're dealing with raw pointers, let's define what we mean by that. -static auto hasPointerType() { - return hasType(hasCanonicalType(pointerType())); +static bool hasPointerType(const Expr &E) { + return isa(E.getType().getCanonicalType()); } -static auto hasArrayType() { return hasType(hasCanonicalType(arrayType())); } - -AST_MATCHER_P(Stmt, forEachDescendantEvaluatedStmt, internal::Matcher, - innerMatcher) { - const DynTypedMatcher &DTM = static_cast(innerMatcher); - - MatchDescendantVisitor Visitor(&DTM, Finder, Builder, ASTMatchFinder::BK_All, - true); - return Visitor.findMatch(DynTypedNode::create(Node)); +static bool hasArrayType(const Expr &E) { + return isa(E.getType().getCanonicalType()); } -AST_MATCHER_P(Stmt, forEachDescendantStmt, internal::Matcher, - innerMatcher) { - const DynTypedMatcher &DTM = static_cast(innerMatcher); +static void +forEachDescendantEvaluatedStmt(const Stmt *S, ASTContext &Ctx, + const UnsafeBufferUsageHandler &Handler, + FastMatcher &Matcher) { + MatchDescendantVisitor Visitor(Matcher, /*FindAll=*/true, + /*ignoreUnevaluatedContext=*/true); + Visitor.setASTContext(Ctx); + Visitor.setHandler(Handler); ivanaivanovska wrote: Changed. https://github.com/llvm/llvm-project/pull/125492 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Optimize -Wunsafe-buffer-usage. (PR #125492)
@@ -1670,30 +1936,41 @@ class ULCArraySubscriptGadget : public FixableGadget { }; // Fixable gadget to handle stand alone pointers of the form `UPC(DRE)` in the -// unspecified pointer context (isInUnspecifiedPointerContext). The gadget emits -// fixit of the form `UPC(DRE.data())`. +// unspecified pointer context (findStmtsInUnspecifiedPointerContext). The +// gadget emits fixit of the form `UPC(DRE.data())`. class UPCStandalonePointerGadget : public FixableGadget { private: static constexpr const char *const DeclRefExprTag = "StandalonePointer"; const DeclRefExpr *Node; public: - UPCStandalonePointerGadget(const MatchFinder::MatchResult &Result) + UPCStandalonePointerGadget(const MatchResult &Result) : FixableGadget(Kind::UPCStandalonePointer), -Node(Result.Nodes.getNodeAs(DeclRefExprTag)) { +Node(Result.getNodeAs(DeclRefExprTag)) { assert(Node != nullptr && "Expecting a non-null matching result"); } static bool classof(const Gadget *G) { return G->getKind() == Kind::UPCStandalonePointer; } - static Matcher matcher() { -auto ArrayOrPtr = anyOf(hasPointerType(), hasArrayType()); -auto target = expr(ignoringParenImpCasts( -declRefExpr(allOf(ArrayOrPtr, toSupportedVariable())) -.bind(DeclRefExprTag))); -return stmt(isInUnspecifiedPointerContext(target)); + static bool matches(const Stmt *S, + llvm::SmallVectorImpl &Results) { +bool Found = false; +findStmtsInUnspecifiedPointerContext(S, [&Found, &Results](const Stmt *S) { ivanaivanovska wrote: Removed Found altogether and checking the size of the Results instead. https://github.com/llvm/llvm-project/pull/125492 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Optimize -Wunsafe-buffer-usage. (PR #125492)
ivanaivanovska wrote: Thanks for the review @ziqingluo-90! https://github.com/llvm/llvm-project/pull/125492 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Optimize -Wunsafe-buffer-usage. (PR #125492)
https://github.com/ivanaivanovska closed https://github.com/llvm/llvm-project/pull/125492 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits