tbourvon created this revision.
tbourvon added a reviewer: lebedev.ri.
tbourvon added a project: clang-tools-extra.
Herald added subscribers: hintonda, xazax.hun, mgorny.

This adds a utility matcher (which is placed in `util/Matchers.h`, because it 
uses functions from `ASTMatchFinder.h` which cannot be used from 
`ASTMatchers.h`) used by https://reviews.llvm.org/D37014).


https://reviews.llvm.org/D42624

Files:
  clang-tidy/utils/Matchers.h
  unittests/clang-tidy/CMakeLists.txt
  unittests/clang-tidy/MatchersUtilsTest.cpp

Index: unittests/clang-tidy/MatchersUtilsTest.cpp
===================================================================
--- /dev/null
+++ unittests/clang-tidy/MatchersUtilsTest.cpp
@@ -0,0 +1,25 @@
+#include "../../../unittests/ASTMatchers/ASTMatchersTest.h"
+#include "utils/Matchers.h"
+
+namespace clang {
+namespace tidy {
+namespace test {
+
+using namespace ast_matchers;
+using namespace matchers;
+
+TEST(StatementMatcher, HasSuccessor) {
+  StatementMatcher DeclHasSuccessorReturnStmt =
+    declStmt(hasSuccessor(returnStmt()));
+
+  EXPECT_TRUE(matches(
+    "void foo() { int bar; return; }",
+    DeclHasSuccessorReturnStmt));
+  EXPECT_TRUE(notMatches(
+    "void foo() { int bar; bar++; return; }",
+    DeclHasSuccessorReturnStmt));
+}
+
+}
+}
+}
Index: unittests/clang-tidy/CMakeLists.txt
===================================================================
--- unittests/clang-tidy/CMakeLists.txt
+++ unittests/clang-tidy/CMakeLists.txt
@@ -12,6 +12,7 @@
   IncludeInserterTest.cpp
   GoogleModuleTest.cpp
   LLVMModuleTest.cpp
+  MatchersUtilsTest.cpp
   NamespaceAliaserTest.cpp
   ObjCModuleTest.cpp
   OverlappingReplacementsTest.cpp
Index: clang-tidy/utils/Matchers.h
===================================================================
--- clang-tidy/utils/Matchers.h
+++ clang-tidy/utils/Matchers.h
@@ -12,6 +12,8 @@
 
 #include "TypeTraits.h"
 #include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Analysis/CFG.h"
 
 namespace clang {
 namespace tidy {
@@ -48,6 +50,67 @@
   return referenceType(pointee(qualType(isConstQualified())));
 }
 
+// Matches the next statement within the parent statement sequence.
+AST_MATCHER_P(Stmt, hasSuccessor,
+              ast_matchers::internal::Matcher<Stmt>, InnerMatcher) {
+  using namespace ast_matchers;
+
+  // We get the first parent, making sure that we're not in a case statement
+  // not in a compound statement directly inside a switch, because this causes
+  // the buildCFG call to crash.
+  auto Parent = selectFirst<Stmt>(
+    "parent",
+    match(
+      stmt(hasAncestor(stmt(
+        unless(caseStmt()),
+        unless(compoundStmt(hasParent(switchStmt()))),
+        stmt().bind("parent")))),
+    Node, Finder->getASTContext()));
+
+  // We build a Control Flow Graph (CFG) from the parent statement.
+  std::unique_ptr<CFG> StatementCFG =
+    CFG::buildCFG(nullptr, const_cast<Stmt*>(Parent), &Finder->getASTContext(),
+                  CFG::BuildOptions());
+
+  if (!StatementCFG) {
+    return false;
+  }
+
+  // We iterate through all the CFGBlocks, which basically means that we go over
+  // all the possible branches of the code and therefore cover all statements.
+  for (auto& Block : *StatementCFG) {
+    if (!Block) {
+      continue;
+    }
+
+    // We iterate through all the statements of the block.
+    bool ReturnNextStmt = false;
+    for (auto& BlockItem : *Block) {
+      Optional<CFGStmt> CFGStatement = BlockItem.getAs<CFGStmt>();
+      if (!CFGStatement) {
+        if (ReturnNextStmt) {
+          return false;
+        }
+
+        continue;
+      }
+
+      // If we found the next statement, we apply the inner matcher and return
+      // the result.
+      if (ReturnNextStmt) {
+        return InnerMatcher.matches(*CFGStatement->getStmt(), Finder, Builder);
+      }
+
+      if (CFGStatement->getStmt() == &Node) {
+        ReturnNextStmt = true;
+      }
+    }
+  }
+
+  // If we didn't find a successor, we just return false.
+  return false;
+}
+
 } // namespace matchers
 } // namespace tidy
 } // namespace clang
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to