samestep created this revision.
Herald added subscribers: martong, tschuett, xazax.hun.
Herald added a project: All.
samestep requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D128467

Files:
  clang/include/clang/Analysis/FlowSensitive/MatchSwitch.h
  clang/unittests/Analysis/FlowSensitive/MatchSwitchTest.cpp

Index: clang/unittests/Analysis/FlowSensitive/MatchSwitchTest.cpp
===================================================================
--- clang/unittests/Analysis/FlowSensitive/MatchSwitchTest.cpp
+++ clang/unittests/Analysis/FlowSensitive/MatchSwitchTest.cpp
@@ -204,3 +204,29 @@
   RunDataflow(Code,
               UnorderedElementsAre(Pair("p", Holds(BooleanLattice(false)))));
 }
+
+TEST_F(MatchSwitchTest, ReturnNonVoid) {
+  using namespace ast_matchers;
+
+  auto Unit =
+      tooling::buildASTFromCode("void f() { int x = 42; }", "input.cc",
+                                std::make_shared<PCHContainerOperations>());
+  auto &Context = Unit->getASTContext();
+  const auto *S =
+      selectFirst<FunctionDecl>(
+          "f",
+          match(functionDecl(isDefinition(), hasName("f")).bind("f"), Context))
+          ->getBody();
+
+  MatchSwitch<const int, std::vector<int>> Switch =
+      MatchSwitchBuilder<const int, std::vector<int>>()
+          .CaseOf<Stmt>(stmt(),
+                        [](const Stmt *, const MatchFinder::MatchResult &,
+                           const int &State) -> std::vector<int> {
+                          return {1, State, 3};
+                        })
+          .Build();
+  std::vector<int> Actual = Switch(*S, Context, 7);
+  std::vector<int> Expected{1, 7, 3};
+  EXPECT_EQ(Actual, Expected);
+}
Index: clang/include/clang/Analysis/FlowSensitive/MatchSwitch.h
===================================================================
--- clang/include/clang/Analysis/FlowSensitive/MatchSwitch.h
+++ clang/include/clang/Analysis/FlowSensitive/MatchSwitch.h
@@ -46,8 +46,8 @@
 
 /// Matches against `Stmt` and, based on its structure, dispatches to an
 /// appropriate handler.
-template <typename State>
-using MatchSwitch = std::function<void(const Stmt &, ASTContext &, State &)>;
+template <typename State, typename Output = void>
+using MatchSwitch = std::function<Output(const Stmt &, ASTContext &, State &)>;
 
 /// Collects cases of a "match switch": a collection of matchers paired with
 /// callbacks, which together define a switch that can be applied to a
@@ -68,7 +68,7 @@
 ///     .Build();
 /// }
 /// \endcode
-template <typename State> class MatchSwitchBuilder {
+template <typename State, typename Output = void> class MatchSwitchBuilder {
 public:
   /// Registers an action that will be triggered by the match of a pattern
   /// against the input statement.
@@ -79,24 +79,24 @@
   template <typename Node>
   MatchSwitchBuilder &&
   CaseOf(ast_matchers::internal::Matcher<Stmt> M,
-         std::function<void(const Node *,
-                            const ast_matchers::MatchFinder::MatchResult &,
-                            State &)>
+         std::function<Output(const Node *,
+                              const ast_matchers::MatchFinder::MatchResult &,
+                              State &)>
              A) && {
     Matchers.push_back(std::move(M));
     Actions.push_back(
         [A = std::move(A)](const Stmt *Stmt,
                            const ast_matchers::MatchFinder::MatchResult &R,
-                           State &S) { A(cast<Node>(Stmt), R, S); });
+                           State &S) { return A(cast<Node>(Stmt), R, S); });
     return std::move(*this);
   }
 
-  MatchSwitch<State> Build() && {
+  MatchSwitch<State, Output> Build() && {
     return [Matcher = BuildMatcher(), Actions = std::move(Actions)](
-               const Stmt &Stmt, ASTContext &Context, State &S) {
+               const Stmt &Stmt, ASTContext &Context, State &S) -> Output {
       auto Results = ast_matchers::matchDynamic(Matcher, Stmt, Context);
       if (Results.empty())
-        return;
+        return {};
       // Look through the map for the first binding of the form "TagN..." use
       // that to select the action.
       for (const auto &Element : Results[0].getMap()) {
@@ -104,12 +104,12 @@
         size_t Index = 0;
         if (ID.consume_front("Tag") && !ID.getAsInteger(10, Index) &&
             Index < Actions.size()) {
-          Actions[Index](
+          return Actions[Index](
               &Stmt,
               ast_matchers::MatchFinder::MatchResult(Results[0], &Context), S);
-          return;
         }
       }
+      return {};
     };
   }
 
@@ -142,7 +142,7 @@
   }
 
   std::vector<ast_matchers::internal::DynTypedMatcher> Matchers;
-  std::vector<std::function<void(
+  std::vector<std::function<Output(
       const Stmt *, const ast_matchers::MatchFinder::MatchResult &, State &)>>
       Actions;
 };
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to