r311664 - Fix use-after-free in Clang's ASTSelection unittest

Alex Lorenz via cfe-commits cfe-commits at lists.llvm.org
Thu Aug 24 07:53:48 PDT 2017


Author: arphaman
Date: Thu Aug 24 07:53:48 2017
New Revision: 311664

URL: http://llvm.org/viewvc/llvm-project?rev=311664&view=rev
Log:
Fix use-after-free in Clang's ASTSelection unittest

Modified:
    cfe/trunk/unittests/Tooling/ASTSelectionTest.cpp

Modified: cfe/trunk/unittests/Tooling/ASTSelectionTest.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Tooling/ASTSelectionTest.cpp?rev=311664&r1=311663&r2=311664&view=diff
==============================================================================
--- cfe/trunk/unittests/Tooling/ASTSelectionTest.cpp (original)
+++ cfe/trunk/unittests/Tooling/ASTSelectionTest.cpp Thu Aug 24 07:53:48 2017
@@ -29,13 +29,14 @@ using FileRange = std::pair<FileLocation
 class SelectionFinderVisitor : public TestVisitor<SelectionFinderVisitor> {
   FileLocation Location;
   Optional<FileRange> SelectionRange;
+  llvm::function_ref<void(Optional<SelectedASTNode>)> Consumer;
 
 public:
-  Optional<SelectedASTNode> Selection;
-
-  SelectionFinderVisitor(FileLocation Location,
-                         Optional<FileRange> SelectionRange)
-      : Location(Location), SelectionRange(SelectionRange) {}
+  SelectionFinderVisitor(
+      FileLocation Location, Optional<FileRange> SelectionRange,
+      llvm::function_ref<void(Optional<SelectedASTNode>)> Consumer)
+      : Location(Location), SelectionRange(SelectionRange), Consumer(Consumer) {
+  }
 
   bool VisitTranslationUnitDecl(const TranslationUnitDecl *TU) {
     const ASTContext &Context = TU->getASTContext();
@@ -49,19 +50,18 @@ public:
       SourceLocation Loc = Location.translate(SM);
       SelRange = SourceRange(Loc, Loc);
     }
-    Selection = findSelectedASTNodes(Context, SelRange);
+    Consumer(findSelectedASTNodes(Context, SelRange));
     return false;
   }
 };
 
-Optional<SelectedASTNode>
-findSelectedASTNodes(StringRef Source, FileLocation Location,
-                     Optional<FileRange> SelectionRange,
-                     SelectionFinderVisitor::Language Language =
-                         SelectionFinderVisitor::Lang_CXX11) {
-  SelectionFinderVisitor Visitor(Location, SelectionRange);
+void findSelectedASTNodes(
+    StringRef Source, FileLocation Location, Optional<FileRange> SelectionRange,
+    llvm::function_ref<void(Optional<SelectedASTNode>)> Consumer,
+    SelectionFinderVisitor::Language Language =
+        SelectionFinderVisitor::Lang_CXX11) {
+  SelectionFinderVisitor Visitor(Location, SelectionRange, Consumer);
   EXPECT_TRUE(Visitor.runOver(Source, Language));
-  return std::move(Visitor.Selection);
 }
 
 void checkNodeImpl(bool IsTypeMatched, const SelectedASTNode &Node,
@@ -125,123 +125,126 @@ ForAllChildrenOf allChildrenOf(const Sel
 }
 
 TEST(ASTSelectionFinder, CursorNoSelection) {
-  Optional<SelectedASTNode> Node =
-      findSelectedASTNodes(" void f() { }", {1, 1}, None);
-  EXPECT_FALSE(Node);
+  findSelectedASTNodes(
+      " void f() { }", {1, 1}, None,
+      [](Optional<SelectedASTNode> Node) { EXPECT_FALSE(Node); });
 }
 
 TEST(ASTSelectionFinder, CursorAtStartOfFunction) {
-  Optional<SelectedASTNode> Node =
-      findSelectedASTNodes("void f() { }", {1, 1}, None);
-  EXPECT_TRUE(Node);
-  checkNode<TranslationUnitDecl>(*Node, SourceSelectionKind::None,
-                                 /*NumChildren=*/1);
-  checkNode<FunctionDecl>(Node->Children[0],
-                          SourceSelectionKind::ContainsSelection,
-                          /*NumChildren=*/0, /*Name=*/"f");
-
-  // Check that the dumping works.
-  std::string DumpValue;
-  llvm::raw_string_ostream OS(DumpValue);
-  Node->Children[0].dump(OS);
-  ASSERT_EQ(OS.str(), "FunctionDecl \"f\" contains-selection\n");
+  findSelectedASTNodes(
+      "void f() { }", {1, 1}, None, [](Optional<SelectedASTNode> Node) {
+        EXPECT_TRUE(Node);
+        checkNode<TranslationUnitDecl>(*Node, SourceSelectionKind::None,
+                                       /*NumChildren=*/1);
+        checkNode<FunctionDecl>(Node->Children[0],
+                                SourceSelectionKind::ContainsSelection,
+                                /*NumChildren=*/0, /*Name=*/"f");
+
+        // Check that the dumping works.
+        std::string DumpValue;
+        llvm::raw_string_ostream OS(DumpValue);
+        Node->Children[0].dump(OS);
+        ASSERT_EQ(OS.str(), "FunctionDecl \"f\" contains-selection\n");
+      });
 }
 
 TEST(ASTSelectionFinder, RangeNoSelection) {
-  {
-    Optional<SelectedASTNode> Node = findSelectedASTNodes(
-        " void f() { }", {1, 1}, FileRange{{1, 1}, {1, 1}});
-    EXPECT_FALSE(Node);
-  }
-  {
-    Optional<SelectedASTNode> Node = findSelectedASTNodes(
-        "  void f() { }", {1, 1}, FileRange{{1, 1}, {1, 2}});
-    EXPECT_FALSE(Node);
-  }
+  findSelectedASTNodes(
+      " void f() { }", {1, 1}, FileRange{{1, 1}, {1, 1}},
+      [](Optional<SelectedASTNode> Node) { EXPECT_FALSE(Node); });
+  findSelectedASTNodes(
+      "  void f() { }", {1, 1}, FileRange{{1, 1}, {1, 2}},
+      [](Optional<SelectedASTNode> Node) { EXPECT_FALSE(Node); });
 }
 
 TEST(ASTSelectionFinder, EmptyRangeFallbackToCursor) {
-  Optional<SelectedASTNode> Node =
-      findSelectedASTNodes("void f() { }", {1, 1}, FileRange{{1, 1}, {1, 1}});
-  EXPECT_TRUE(Node);
-  checkNode<FunctionDecl>(Node->Children[0],
-                          SourceSelectionKind::ContainsSelection,
-                          /*NumChildren=*/0, /*Name=*/"f");
+  findSelectedASTNodes("void f() { }", {1, 1}, FileRange{{1, 1}, {1, 1}},
+                       [](Optional<SelectedASTNode> Node) {
+                         EXPECT_TRUE(Node);
+                         checkNode<FunctionDecl>(
+                             Node->Children[0],
+                             SourceSelectionKind::ContainsSelection,
+                             /*NumChildren=*/0, /*Name=*/"f");
+                       });
 }
 
 TEST(ASTSelectionFinder, WholeFunctionSelection) {
   StringRef Source = "int f(int x) { return x;\n}\nvoid f2() { }";
   // From 'int' until just after '}':
-  {
-    auto Node = findSelectedASTNodes(Source, {1, 1}, FileRange{{1, 1}, {2, 2}});
-    EXPECT_TRUE(Node);
-    EXPECT_EQ(Node->Children.size(), 1u);
-    const auto &Fn = checkNode<FunctionDecl>(
-        Node->Children[0], SourceSelectionKind::ContainsSelection,
-        /*NumChildren=*/2, /*Name=*/"f");
-    checkNode<ParmVarDecl>(Fn.Children[0],
-                           SourceSelectionKind::InsideSelection);
-    const auto &Body = checkNode<CompoundStmt>(
-        Fn.Children[1], SourceSelectionKind::InsideSelection,
-        /*NumChildren=*/1);
-    const auto &Return = checkNode<ReturnStmt>(
-        Body.Children[0], SourceSelectionKind::InsideSelection,
-        /*NumChildren=*/1);
-    checkNode<ImplicitCastExpr>(Return.Children[0],
-                                SourceSelectionKind::InsideSelection,
-                                /*NumChildren=*/1);
-    checkNode<DeclRefExpr>(Return.Children[0].Children[0],
-                           SourceSelectionKind::InsideSelection);
-  }
+
+  findSelectedASTNodes(
+      Source, {1, 1}, FileRange{{1, 1}, {2, 2}},
+      [](Optional<SelectedASTNode> Node) {
+        EXPECT_TRUE(Node);
+        EXPECT_EQ(Node->Children.size(), 1u);
+        const auto &Fn = checkNode<FunctionDecl>(
+            Node->Children[0], SourceSelectionKind::ContainsSelection,
+            /*NumChildren=*/2, /*Name=*/"f");
+        checkNode<ParmVarDecl>(Fn.Children[0],
+                               SourceSelectionKind::InsideSelection);
+        const auto &Body = checkNode<CompoundStmt>(
+            Fn.Children[1], SourceSelectionKind::InsideSelection,
+            /*NumChildren=*/1);
+        const auto &Return = checkNode<ReturnStmt>(
+            Body.Children[0], SourceSelectionKind::InsideSelection,
+            /*NumChildren=*/1);
+        checkNode<ImplicitCastExpr>(Return.Children[0],
+                                    SourceSelectionKind::InsideSelection,
+                                    /*NumChildren=*/1);
+        checkNode<DeclRefExpr>(Return.Children[0].Children[0],
+                               SourceSelectionKind::InsideSelection);
+      });
+
   // From 'int' until just before '}':
-  {
-    auto Node = findSelectedASTNodes(Source, {2, 1}, FileRange{{1, 1}, {2, 1}});
-    EXPECT_TRUE(Node);
-    EXPECT_EQ(Node->Children.size(), 1u);
-    const auto &Fn = checkNode<FunctionDecl>(
-        Node->Children[0], SourceSelectionKind::ContainsSelection,
-        /*NumChildren=*/2, /*Name=*/"f");
-    const auto &Body = checkNode<CompoundStmt>(
-        Fn.Children[1], SourceSelectionKind::ContainsSelectionEnd,
-        /*NumChildren=*/1);
-    checkNode<ReturnStmt>(Body.Children[0],
-                          SourceSelectionKind::InsideSelection,
-                          /*NumChildren=*/1);
-  }
+  findSelectedASTNodes(
+      Source, {2, 1}, FileRange{{1, 1}, {2, 1}},
+      [](Optional<SelectedASTNode> Node) {
+        EXPECT_TRUE(Node);
+        EXPECT_EQ(Node->Children.size(), 1u);
+        const auto &Fn = checkNode<FunctionDecl>(
+            Node->Children[0], SourceSelectionKind::ContainsSelection,
+            /*NumChildren=*/2, /*Name=*/"f");
+        const auto &Body = checkNode<CompoundStmt>(
+            Fn.Children[1], SourceSelectionKind::ContainsSelectionEnd,
+            /*NumChildren=*/1);
+        checkNode<ReturnStmt>(Body.Children[0],
+                              SourceSelectionKind::InsideSelection,
+                              /*NumChildren=*/1);
+      });
   // From '{' until just after '}':
-  {
-    auto Node =
-        findSelectedASTNodes(Source, {1, 14}, FileRange{{1, 14}, {2, 2}});
-    EXPECT_TRUE(Node);
-    EXPECT_EQ(Node->Children.size(), 1u);
-    const auto &Fn = checkNode<FunctionDecl>(
-        Node->Children[0], SourceSelectionKind::ContainsSelection,
-        /*NumChildren=*/1, /*Name=*/"f");
-    const auto &Body = checkNode<CompoundStmt>(
-        Fn.Children[0], SourceSelectionKind::ContainsSelection,
-        /*NumChildren=*/1);
-    checkNode<ReturnStmt>(Body.Children[0],
-                          SourceSelectionKind::InsideSelection,
-                          /*NumChildren=*/1);
-  }
+  findSelectedASTNodes(
+      Source, {1, 14}, FileRange{{1, 14}, {2, 2}},
+      [](Optional<SelectedASTNode> Node) {
+        EXPECT_TRUE(Node);
+        EXPECT_EQ(Node->Children.size(), 1u);
+        const auto &Fn = checkNode<FunctionDecl>(
+            Node->Children[0], SourceSelectionKind::ContainsSelection,
+            /*NumChildren=*/1, /*Name=*/"f");
+        const auto &Body = checkNode<CompoundStmt>(
+            Fn.Children[0], SourceSelectionKind::ContainsSelection,
+            /*NumChildren=*/1);
+        checkNode<ReturnStmt>(Body.Children[0],
+                              SourceSelectionKind::InsideSelection,
+                              /*NumChildren=*/1);
+      });
   // From 'x' until just after '}':
-  {
-    auto Node =
-        findSelectedASTNodes(Source, {2, 2}, FileRange{{1, 11}, {2, 2}});
-    EXPECT_TRUE(Node);
-    EXPECT_EQ(Node->Children.size(), 1u);
-    const auto &Fn = checkNode<FunctionDecl>(
-        Node->Children[0], SourceSelectionKind::ContainsSelection,
-        /*NumChildren=*/2, /*Name=*/"f");
-    checkNode<ParmVarDecl>(Fn.Children[0],
-                           SourceSelectionKind::ContainsSelectionStart);
-    const auto &Body = checkNode<CompoundStmt>(
-        Fn.Children[1], SourceSelectionKind::InsideSelection,
-        /*NumChildren=*/1);
-    checkNode<ReturnStmt>(Body.Children[0],
-                          SourceSelectionKind::InsideSelection,
-                          /*NumChildren=*/1);
-  }
+  findSelectedASTNodes(
+      Source, {2, 2}, FileRange{{1, 11}, {2, 2}},
+      [](Optional<SelectedASTNode> Node) {
+        EXPECT_TRUE(Node);
+        EXPECT_EQ(Node->Children.size(), 1u);
+        const auto &Fn = checkNode<FunctionDecl>(
+            Node->Children[0], SourceSelectionKind::ContainsSelection,
+            /*NumChildren=*/2, /*Name=*/"f");
+        checkNode<ParmVarDecl>(Fn.Children[0],
+                               SourceSelectionKind::ContainsSelectionStart);
+        const auto &Body = checkNode<CompoundStmt>(
+            Fn.Children[1], SourceSelectionKind::InsideSelection,
+            /*NumChildren=*/1);
+        checkNode<ReturnStmt>(Body.Children[0],
+                              SourceSelectionKind::InsideSelection,
+                              /*NumChildren=*/1);
+      });
 }
 
 TEST(ASTSelectionFinder, MultipleFunctionSelection) {
@@ -262,10 +265,10 @@ void f3() { }
                             /*NumChildren=*/1, /*Name=*/"f2");
   };
   // Just after '}' of f0 and just before 'void' of f3:
-  SelectedF1F2(findSelectedASTNodes(Source, {2, 2}, FileRange{{2, 2}, {5, 1}}));
+  findSelectedASTNodes(Source, {2, 2}, FileRange{{2, 2}, {5, 1}}, SelectedF1F2);
   // Just before 'void' of f1 and just after '}' of f2:
-  SelectedF1F2(
-      findSelectedASTNodes(Source, {3, 1}, FileRange{{3, 1}, {4, 14}}));
+  findSelectedASTNodes(Source, {3, 1}, FileRange{{3, 1}, {4, 14}},
+                       SelectedF1F2);
 }
 
 TEST(ASTSelectionFinder, MultipleStatementSelection) {
@@ -279,67 +282,73 @@ TEST(ASTSelectionFinder, MultipleStateme
   return;
 })";
   // From 'f(2,3)' until just before 'x = 1;':
-  {
-    auto Node = findSelectedASTNodes(Source, {3, 2}, FileRange{{3, 2}, {7, 1}});
-    EXPECT_TRUE(Node);
-    EXPECT_EQ(Node->Children.size(), 1u);
-    const auto &Fn = checkNode<FunctionDecl>(
-        Node->Children[0], SourceSelectionKind::ContainsSelection,
-        /*NumChildren=*/1, /*Name=*/"f");
-    const auto &Body = checkNode<CompoundStmt>(
-        Fn.Children[0], SourceSelectionKind::ContainsSelection,
-        /*NumChildren=*/2);
-    allChildrenOf(checkNode<CallExpr>(Body.Children[0],
-                                      SourceSelectionKind::InsideSelection,
-                                      /*NumChildren=*/3))
-        .shouldHaveSelectionKind(SourceSelectionKind::InsideSelection);
-    allChildrenOf(checkNode<IfStmt>(Body.Children[1],
-                                    SourceSelectionKind::InsideSelection,
-                                    /*NumChildren=*/2))
-        .shouldHaveSelectionKind(SourceSelectionKind::InsideSelection);
-  }
+  findSelectedASTNodes(
+      Source, {3, 2}, FileRange{{3, 2}, {7, 1}},
+      [](Optional<SelectedASTNode> Node) {
+        EXPECT_TRUE(Node);
+        EXPECT_EQ(Node->Children.size(), 1u);
+        const auto &Fn = checkNode<FunctionDecl>(
+            Node->Children[0], SourceSelectionKind::ContainsSelection,
+            /*NumChildren=*/1, /*Name=*/"f");
+        const auto &Body = checkNode<CompoundStmt>(
+            Fn.Children[0], SourceSelectionKind::ContainsSelection,
+            /*NumChildren=*/2);
+        allChildrenOf(checkNode<CallExpr>(Body.Children[0],
+                                          SourceSelectionKind::InsideSelection,
+                                          /*NumChildren=*/3))
+            .shouldHaveSelectionKind(SourceSelectionKind::InsideSelection);
+        allChildrenOf(checkNode<IfStmt>(Body.Children[1],
+                                        SourceSelectionKind::InsideSelection,
+                                        /*NumChildren=*/2))
+            .shouldHaveSelectionKind(SourceSelectionKind::InsideSelection);
+      });
   // From 'f(2,3)' until just before ';' in 'x = 1;':
-  {
-    auto Node = findSelectedASTNodes(Source, {3, 2}, FileRange{{3, 2}, {7, 8}});
-    EXPECT_TRUE(Node);
-    EXPECT_EQ(Node->Children.size(), 1u);
-    const auto &Fn = checkNode<FunctionDecl>(
-        Node->Children[0], SourceSelectionKind::ContainsSelection,
-        /*NumChildren=*/1, /*Name=*/"f");
-    const auto &Body = checkNode<CompoundStmt>(
-        Fn.Children[0], SourceSelectionKind::ContainsSelection,
-        /*NumChildren=*/3);
-    checkNode<CallExpr>(Body.Children[0], SourceSelectionKind::InsideSelection,
-                        /*NumChildren=*/3);
-    checkNode<IfStmt>(Body.Children[1], SourceSelectionKind::InsideSelection,
-                      /*NumChildren=*/2);
-    checkNode<BinaryOperator>(Body.Children[2],
-                              SourceSelectionKind::InsideSelection,
-                              /*NumChildren=*/2);
-  }
+  findSelectedASTNodes(
+      Source, {3, 2}, FileRange{{3, 2}, {7, 8}},
+      [](Optional<SelectedASTNode> Node) {
+        EXPECT_TRUE(Node);
+        EXPECT_EQ(Node->Children.size(), 1u);
+        const auto &Fn = checkNode<FunctionDecl>(
+            Node->Children[0], SourceSelectionKind::ContainsSelection,
+            /*NumChildren=*/1, /*Name=*/"f");
+        const auto &Body = checkNode<CompoundStmt>(
+            Fn.Children[0], SourceSelectionKind::ContainsSelection,
+            /*NumChildren=*/3);
+        checkNode<CallExpr>(Body.Children[0],
+                            SourceSelectionKind::InsideSelection,
+                            /*NumChildren=*/3);
+        checkNode<IfStmt>(Body.Children[1],
+                          SourceSelectionKind::InsideSelection,
+                          /*NumChildren=*/2);
+        checkNode<BinaryOperator>(Body.Children[2],
+                                  SourceSelectionKind::InsideSelection,
+                                  /*NumChildren=*/2);
+      });
   // From the middle of 'int z = 3' until the middle of 'x = 1;':
-  {
-    auto Node =
-        findSelectedASTNodes(Source, {2, 10}, FileRange{{2, 10}, {7, 5}});
-    EXPECT_TRUE(Node);
-    EXPECT_EQ(Node->Children.size(), 1u);
-    const auto &Fn = checkNode<FunctionDecl>(
-        Node->Children[0], SourceSelectionKind::ContainsSelection,
-        /*NumChildren=*/1, /*Name=*/"f");
-    const auto &Body = checkNode<CompoundStmt>(
-        Fn.Children[0], SourceSelectionKind::ContainsSelection,
-        /*NumChildren=*/4);
-    checkNode<DeclStmt>(Body.Children[0],
-                        SourceSelectionKind::ContainsSelectionStart,
-                        /*NumChildren=*/1);
-    checkNode<CallExpr>(Body.Children[1], SourceSelectionKind::InsideSelection,
-                        /*NumChildren=*/3);
-    checkNode<IfStmt>(Body.Children[2], SourceSelectionKind::InsideSelection,
-                      /*NumChildren=*/2);
-    checkNode<BinaryOperator>(Body.Children[3],
-                              SourceSelectionKind::ContainsSelectionEnd,
-                              /*NumChildren=*/1);
-  }
+  findSelectedASTNodes(
+      Source, {2, 10}, FileRange{{2, 10}, {7, 5}},
+      [](Optional<SelectedASTNode> Node) {
+        EXPECT_TRUE(Node);
+        EXPECT_EQ(Node->Children.size(), 1u);
+        const auto &Fn = checkNode<FunctionDecl>(
+            Node->Children[0], SourceSelectionKind::ContainsSelection,
+            /*NumChildren=*/1, /*Name=*/"f");
+        const auto &Body = checkNode<CompoundStmt>(
+            Fn.Children[0], SourceSelectionKind::ContainsSelection,
+            /*NumChildren=*/4);
+        checkNode<DeclStmt>(Body.Children[0],
+                            SourceSelectionKind::ContainsSelectionStart,
+                            /*NumChildren=*/1);
+        checkNode<CallExpr>(Body.Children[1],
+                            SourceSelectionKind::InsideSelection,
+                            /*NumChildren=*/3);
+        checkNode<IfStmt>(Body.Children[2],
+                          SourceSelectionKind::InsideSelection,
+                          /*NumChildren=*/2);
+        checkNode<BinaryOperator>(Body.Children[3],
+                                  SourceSelectionKind::ContainsSelectionEnd,
+                                  /*NumChildren=*/1);
+      });
 }
 
 TEST(ASTSelectionFinder, SelectionInFunctionInObjCImplementation) {
@@ -364,72 +373,72 @@ void catF() { }
 void outerFunction() { }
 )";
   // Just the 'x' expression in 'selected':
-  {
-    auto Node =
-        findSelectedASTNodes(Source, {9, 10}, FileRange{{9, 10}, {9, 11}},
-                             SelectionFinderVisitor::Lang_OBJC);
-    EXPECT_TRUE(Node);
-    EXPECT_EQ(Node->Children.size(), 1u);
-    const auto &Impl = checkNode<ObjCImplementationDecl>(
-        Node->Children[0], SourceSelectionKind::ContainsSelection,
-        /*NumChildren=*/1, /*Name=*/"I");
-    const auto &Fn = checkNode<FunctionDecl>(
-        Impl.Children[0], SourceSelectionKind::ContainsSelection,
-        /*NumChildren=*/1, /*Name=*/"selected");
-    allChildrenOf(Fn).shouldHaveSelectionKind(
-        SourceSelectionKind::ContainsSelection);
-  }
+  findSelectedASTNodes(
+      Source, {9, 10}, FileRange{{9, 10}, {9, 11}},
+      [](Optional<SelectedASTNode> Node) {
+        EXPECT_TRUE(Node);
+        EXPECT_EQ(Node->Children.size(), 1u);
+        const auto &Impl = checkNode<ObjCImplementationDecl>(
+            Node->Children[0], SourceSelectionKind::ContainsSelection,
+            /*NumChildren=*/1, /*Name=*/"I");
+        const auto &Fn = checkNode<FunctionDecl>(
+            Impl.Children[0], SourceSelectionKind::ContainsSelection,
+            /*NumChildren=*/1, /*Name=*/"selected");
+        allChildrenOf(Fn).shouldHaveSelectionKind(
+            SourceSelectionKind::ContainsSelection);
+      },
+      SelectionFinderVisitor::Lang_OBJC);
   // The entire 'catF':
-  {
-    auto Node =
-        findSelectedASTNodes(Source, {15, 1}, FileRange{{15, 1}, {15, 16}},
-                             SelectionFinderVisitor::Lang_OBJC);
-    EXPECT_TRUE(Node);
-    EXPECT_EQ(Node->Children.size(), 1u);
-    const auto &Impl = checkNode<ObjCCategoryImplDecl>(
-        Node->Children[0], SourceSelectionKind::ContainsSelection,
-        /*NumChildren=*/1, /*Name=*/"Cat");
-    const auto &Fn = checkNode<FunctionDecl>(
-        Impl.Children[0], SourceSelectionKind::ContainsSelection,
-        /*NumChildren=*/1, /*Name=*/"catF");
-    allChildrenOf(Fn).shouldHaveSelectionKind(
-        SourceSelectionKind::ContainsSelection);
-  }
+  findSelectedASTNodes(
+      Source, {15, 1}, FileRange{{15, 1}, {15, 16}},
+      [](Optional<SelectedASTNode> Node) {
+        EXPECT_TRUE(Node);
+        EXPECT_EQ(Node->Children.size(), 1u);
+        const auto &Impl = checkNode<ObjCCategoryImplDecl>(
+            Node->Children[0], SourceSelectionKind::ContainsSelection,
+            /*NumChildren=*/1, /*Name=*/"Cat");
+        const auto &Fn = checkNode<FunctionDecl>(
+            Impl.Children[0], SourceSelectionKind::ContainsSelection,
+            /*NumChildren=*/1, /*Name=*/"catF");
+        allChildrenOf(Fn).shouldHaveSelectionKind(
+            SourceSelectionKind::ContainsSelection);
+      },
+      SelectionFinderVisitor::Lang_OBJC);
   // From the line before 'selected' to the line after 'catF':
-  {
-    auto Node =
-        findSelectedASTNodes(Source, {16, 1}, FileRange{{7, 1}, {16, 1}},
-                             SelectionFinderVisitor::Lang_OBJC);
-    EXPECT_TRUE(Node);
-    EXPECT_EQ(Node->Children.size(), 2u);
-    const auto &Impl = checkNode<ObjCImplementationDecl>(
-        Node->Children[0], SourceSelectionKind::ContainsSelectionStart,
-        /*NumChildren=*/1, /*Name=*/"I");
-    const auto &Selected = checkNode<FunctionDecl>(
-        Impl.Children[0], SourceSelectionKind::InsideSelection,
-        /*NumChildren=*/2, /*Name=*/"selected");
-    allChildrenOf(Selected).shouldHaveSelectionKind(
-        SourceSelectionKind::InsideSelection);
-    const auto &Cat = checkNode<ObjCCategoryImplDecl>(
-        Node->Children[1], SourceSelectionKind::ContainsSelectionEnd,
-        /*NumChildren=*/1, /*Name=*/"Cat");
-    const auto &CatF = checkNode<FunctionDecl>(
-        Cat.Children[0], SourceSelectionKind::InsideSelection,
-        /*NumChildren=*/1, /*Name=*/"catF");
-    allChildrenOf(CatF).shouldHaveSelectionKind(
-        SourceSelectionKind::InsideSelection);
-  }
+  findSelectedASTNodes(
+      Source, {16, 1}, FileRange{{7, 1}, {16, 1}},
+      [](Optional<SelectedASTNode> Node) {
+        EXPECT_TRUE(Node);
+        EXPECT_EQ(Node->Children.size(), 2u);
+        const auto &Impl = checkNode<ObjCImplementationDecl>(
+            Node->Children[0], SourceSelectionKind::ContainsSelectionStart,
+            /*NumChildren=*/1, /*Name=*/"I");
+        const auto &Selected = checkNode<FunctionDecl>(
+            Impl.Children[0], SourceSelectionKind::InsideSelection,
+            /*NumChildren=*/2, /*Name=*/"selected");
+        allChildrenOf(Selected).shouldHaveSelectionKind(
+            SourceSelectionKind::InsideSelection);
+        const auto &Cat = checkNode<ObjCCategoryImplDecl>(
+            Node->Children[1], SourceSelectionKind::ContainsSelectionEnd,
+            /*NumChildren=*/1, /*Name=*/"Cat");
+        const auto &CatF = checkNode<FunctionDecl>(
+            Cat.Children[0], SourceSelectionKind::InsideSelection,
+            /*NumChildren=*/1, /*Name=*/"catF");
+        allChildrenOf(CatF).shouldHaveSelectionKind(
+            SourceSelectionKind::InsideSelection);
+      },
+      SelectionFinderVisitor::Lang_OBJC);
   // Just the 'outer' function:
-  {
-    auto Node =
-        findSelectedASTNodes(Source, {19, 1}, FileRange{{19, 1}, {19, 25}},
-                             SelectionFinderVisitor::Lang_OBJC);
-    EXPECT_TRUE(Node);
-    EXPECT_EQ(Node->Children.size(), 1u);
-    checkNode<FunctionDecl>(Node->Children[0],
-                            SourceSelectionKind::ContainsSelection,
-                            /*NumChildren=*/1, /*Name=*/"outerFunction");
-  }
+  findSelectedASTNodes(Source, {19, 1}, FileRange{{19, 1}, {19, 25}},
+                       [](Optional<SelectedASTNode> Node) {
+                         EXPECT_TRUE(Node);
+                         EXPECT_EQ(Node->Children.size(), 1u);
+                         checkNode<FunctionDecl>(
+                             Node->Children[0],
+                             SourceSelectionKind::ContainsSelection,
+                             /*NumChildren=*/1, /*Name=*/"outerFunction");
+                       },
+                       SelectionFinderVisitor::Lang_OBJC);
 }
 
 TEST(ASTSelectionFinder, FunctionInObjCImplementationCarefulWithEarlyExit) {
@@ -446,18 +455,19 @@ void selected() {
 @end
 )";
   // Just 'selected'
-  {
-    auto Node = findSelectedASTNodes(Source, {6, 1}, FileRange{{6, 1}, {7, 2}},
-                                     SelectionFinderVisitor::Lang_OBJC);
-    EXPECT_TRUE(Node);
-    EXPECT_EQ(Node->Children.size(), 1u);
-    const auto &Impl = checkNode<ObjCImplementationDecl>(
-        Node->Children[0], SourceSelectionKind::ContainsSelection,
-        /*NumChildren=*/1, /*Name=*/"I");
-    checkNode<FunctionDecl>(Impl.Children[0],
-                            SourceSelectionKind::ContainsSelection,
-                            /*NumChildren=*/1, /*Name=*/"selected");
-  }
+  findSelectedASTNodes(
+      Source, {6, 1}, FileRange{{6, 1}, {7, 2}},
+      [](Optional<SelectedASTNode> Node) {
+        EXPECT_TRUE(Node);
+        EXPECT_EQ(Node->Children.size(), 1u);
+        const auto &Impl = checkNode<ObjCImplementationDecl>(
+            Node->Children[0], SourceSelectionKind::ContainsSelection,
+            /*NumChildren=*/1, /*Name=*/"I");
+        checkNode<FunctionDecl>(Impl.Children[0],
+                                SourceSelectionKind::ContainsSelection,
+                                /*NumChildren=*/1, /*Name=*/"selected");
+      },
+      SelectionFinderVisitor::Lang_OBJC);
 }
 
 TEST(ASTSelectionFinder, AvoidImplicitDeclarations) {
@@ -471,14 +481,17 @@ void foo() {
 }
 )";
   // The entire struct 'Copy':
-  auto Node = findSelectedASTNodes(Source, {2, 1}, FileRange{{2, 1}, {4, 3}});
-  EXPECT_TRUE(Node);
-  EXPECT_EQ(Node->Children.size(), 1u);
-  const auto &Record = checkNode<CXXRecordDecl>(
-      Node->Children[0], SourceSelectionKind::InsideSelection,
-      /*NumChildren=*/1, /*Name=*/"Copy");
-  checkNode<FieldDecl>(Record.Children[0],
-                       SourceSelectionKind::InsideSelection);
+  findSelectedASTNodes(
+      Source, {2, 1}, FileRange{{2, 1}, {4, 3}},
+      [](Optional<SelectedASTNode> Node) {
+        EXPECT_TRUE(Node);
+        EXPECT_EQ(Node->Children.size(), 1u);
+        const auto &Record = checkNode<CXXRecordDecl>(
+            Node->Children[0], SourceSelectionKind::InsideSelection,
+            /*NumChildren=*/1, /*Name=*/"Copy");
+        checkNode<FieldDecl>(Record.Children[0],
+                             SourceSelectionKind::InsideSelection);
+      });
 }
 
 } // end anonymous namespace




More information about the cfe-commits mailing list