From: Alex Lorenz Date: Thu, 24 Aug 2017 14:53:48 +0000 (+0000) Subject: Fix use-after-free in Clang's ASTSelection unittest X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=13e76633bb40c51fb1746d74a3ba0ed4c8d55d6d;p=clang Fix use-after-free in Clang's ASTSelection unittest git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@311664 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/unittests/Tooling/ASTSelectionTest.cpp b/unittests/Tooling/ASTSelectionTest.cpp index b4e8bc042b..95326dded8 100644 --- a/unittests/Tooling/ASTSelectionTest.cpp +++ b/unittests/Tooling/ASTSelectionTest.cpp @@ -29,13 +29,14 @@ using FileRange = std::pair; class SelectionFinderVisitor : public TestVisitor { FileLocation Location; Optional SelectionRange; + llvm::function_ref)> Consumer; public: - Optional Selection; - - SelectionFinderVisitor(FileLocation Location, - Optional SelectionRange) - : Location(Location), SelectionRange(SelectionRange) {} + SelectionFinderVisitor( + FileLocation Location, Optional SelectionRange, + llvm::function_ref)> 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 -findSelectedASTNodes(StringRef Source, FileLocation Location, - Optional SelectionRange, - SelectionFinderVisitor::Language Language = - SelectionFinderVisitor::Lang_CXX11) { - SelectionFinderVisitor Visitor(Location, SelectionRange); +void findSelectedASTNodes( + StringRef Source, FileLocation Location, Optional SelectionRange, + llvm::function_ref)> 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 SelectedASTNode &Node) { } TEST(ASTSelectionFinder, CursorNoSelection) { - Optional Node = - findSelectedASTNodes(" void f() { }", {1, 1}, None); - EXPECT_FALSE(Node); + findSelectedASTNodes( + " void f() { }", {1, 1}, None, + [](Optional Node) { EXPECT_FALSE(Node); }); } TEST(ASTSelectionFinder, CursorAtStartOfFunction) { - Optional Node = - findSelectedASTNodes("void f() { }", {1, 1}, None); - EXPECT_TRUE(Node); - checkNode(*Node, SourceSelectionKind::None, - /*NumChildren=*/1); - checkNode(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 Node) { + EXPECT_TRUE(Node); + checkNode(*Node, SourceSelectionKind::None, + /*NumChildren=*/1); + checkNode(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 Node = findSelectedASTNodes( - " void f() { }", {1, 1}, FileRange{{1, 1}, {1, 1}}); - EXPECT_FALSE(Node); - } - { - Optional 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 Node) { EXPECT_FALSE(Node); }); + findSelectedASTNodes( + " void f() { }", {1, 1}, FileRange{{1, 1}, {1, 2}}, + [](Optional Node) { EXPECT_FALSE(Node); }); } TEST(ASTSelectionFinder, EmptyRangeFallbackToCursor) { - Optional Node = - findSelectedASTNodes("void f() { }", {1, 1}, FileRange{{1, 1}, {1, 1}}); - EXPECT_TRUE(Node); - checkNode(Node->Children[0], - SourceSelectionKind::ContainsSelection, - /*NumChildren=*/0, /*Name=*/"f"); + findSelectedASTNodes("void f() { }", {1, 1}, FileRange{{1, 1}, {1, 1}}, + [](Optional Node) { + EXPECT_TRUE(Node); + checkNode( + 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( - Node->Children[0], SourceSelectionKind::ContainsSelection, - /*NumChildren=*/2, /*Name=*/"f"); - checkNode(Fn.Children[0], - SourceSelectionKind::InsideSelection); - const auto &Body = checkNode( - Fn.Children[1], SourceSelectionKind::InsideSelection, - /*NumChildren=*/1); - const auto &Return = checkNode( - Body.Children[0], SourceSelectionKind::InsideSelection, - /*NumChildren=*/1); - checkNode(Return.Children[0], - SourceSelectionKind::InsideSelection, - /*NumChildren=*/1); - checkNode(Return.Children[0].Children[0], - SourceSelectionKind::InsideSelection); - } + + findSelectedASTNodes( + Source, {1, 1}, FileRange{{1, 1}, {2, 2}}, + [](Optional Node) { + EXPECT_TRUE(Node); + EXPECT_EQ(Node->Children.size(), 1u); + const auto &Fn = checkNode( + Node->Children[0], SourceSelectionKind::ContainsSelection, + /*NumChildren=*/2, /*Name=*/"f"); + checkNode(Fn.Children[0], + SourceSelectionKind::InsideSelection); + const auto &Body = checkNode( + Fn.Children[1], SourceSelectionKind::InsideSelection, + /*NumChildren=*/1); + const auto &Return = checkNode( + Body.Children[0], SourceSelectionKind::InsideSelection, + /*NumChildren=*/1); + checkNode(Return.Children[0], + SourceSelectionKind::InsideSelection, + /*NumChildren=*/1); + checkNode(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( - Node->Children[0], SourceSelectionKind::ContainsSelection, - /*NumChildren=*/2, /*Name=*/"f"); - const auto &Body = checkNode( - Fn.Children[1], SourceSelectionKind::ContainsSelectionEnd, - /*NumChildren=*/1); - checkNode(Body.Children[0], - SourceSelectionKind::InsideSelection, - /*NumChildren=*/1); - } + findSelectedASTNodes( + Source, {2, 1}, FileRange{{1, 1}, {2, 1}}, + [](Optional Node) { + EXPECT_TRUE(Node); + EXPECT_EQ(Node->Children.size(), 1u); + const auto &Fn = checkNode( + Node->Children[0], SourceSelectionKind::ContainsSelection, + /*NumChildren=*/2, /*Name=*/"f"); + const auto &Body = checkNode( + Fn.Children[1], SourceSelectionKind::ContainsSelectionEnd, + /*NumChildren=*/1); + checkNode(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( - Node->Children[0], SourceSelectionKind::ContainsSelection, - /*NumChildren=*/1, /*Name=*/"f"); - const auto &Body = checkNode( - Fn.Children[0], SourceSelectionKind::ContainsSelection, - /*NumChildren=*/1); - checkNode(Body.Children[0], - SourceSelectionKind::InsideSelection, - /*NumChildren=*/1); - } + findSelectedASTNodes( + Source, {1, 14}, FileRange{{1, 14}, {2, 2}}, + [](Optional Node) { + EXPECT_TRUE(Node); + EXPECT_EQ(Node->Children.size(), 1u); + const auto &Fn = checkNode( + Node->Children[0], SourceSelectionKind::ContainsSelection, + /*NumChildren=*/1, /*Name=*/"f"); + const auto &Body = checkNode( + Fn.Children[0], SourceSelectionKind::ContainsSelection, + /*NumChildren=*/1); + checkNode(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( - Node->Children[0], SourceSelectionKind::ContainsSelection, - /*NumChildren=*/2, /*Name=*/"f"); - checkNode(Fn.Children[0], - SourceSelectionKind::ContainsSelectionStart); - const auto &Body = checkNode( - Fn.Children[1], SourceSelectionKind::InsideSelection, - /*NumChildren=*/1); - checkNode(Body.Children[0], - SourceSelectionKind::InsideSelection, - /*NumChildren=*/1); - } + findSelectedASTNodes( + Source, {2, 2}, FileRange{{1, 11}, {2, 2}}, + [](Optional Node) { + EXPECT_TRUE(Node); + EXPECT_EQ(Node->Children.size(), 1u); + const auto &Fn = checkNode( + Node->Children[0], SourceSelectionKind::ContainsSelection, + /*NumChildren=*/2, /*Name=*/"f"); + checkNode(Fn.Children[0], + SourceSelectionKind::ContainsSelectionStart); + const auto &Body = checkNode( + Fn.Children[1], SourceSelectionKind::InsideSelection, + /*NumChildren=*/1); + checkNode(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, MultipleStatementSelection) { 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( - Node->Children[0], SourceSelectionKind::ContainsSelection, - /*NumChildren=*/1, /*Name=*/"f"); - const auto &Body = checkNode( - Fn.Children[0], SourceSelectionKind::ContainsSelection, - /*NumChildren=*/2); - allChildrenOf(checkNode(Body.Children[0], - SourceSelectionKind::InsideSelection, - /*NumChildren=*/3)) - .shouldHaveSelectionKind(SourceSelectionKind::InsideSelection); - allChildrenOf(checkNode(Body.Children[1], - SourceSelectionKind::InsideSelection, - /*NumChildren=*/2)) - .shouldHaveSelectionKind(SourceSelectionKind::InsideSelection); - } + findSelectedASTNodes( + Source, {3, 2}, FileRange{{3, 2}, {7, 1}}, + [](Optional Node) { + EXPECT_TRUE(Node); + EXPECT_EQ(Node->Children.size(), 1u); + const auto &Fn = checkNode( + Node->Children[0], SourceSelectionKind::ContainsSelection, + /*NumChildren=*/1, /*Name=*/"f"); + const auto &Body = checkNode( + Fn.Children[0], SourceSelectionKind::ContainsSelection, + /*NumChildren=*/2); + allChildrenOf(checkNode(Body.Children[0], + SourceSelectionKind::InsideSelection, + /*NumChildren=*/3)) + .shouldHaveSelectionKind(SourceSelectionKind::InsideSelection); + allChildrenOf(checkNode(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( - Node->Children[0], SourceSelectionKind::ContainsSelection, - /*NumChildren=*/1, /*Name=*/"f"); - const auto &Body = checkNode( - Fn.Children[0], SourceSelectionKind::ContainsSelection, - /*NumChildren=*/3); - checkNode(Body.Children[0], SourceSelectionKind::InsideSelection, - /*NumChildren=*/3); - checkNode(Body.Children[1], SourceSelectionKind::InsideSelection, - /*NumChildren=*/2); - checkNode(Body.Children[2], - SourceSelectionKind::InsideSelection, - /*NumChildren=*/2); - } + findSelectedASTNodes( + Source, {3, 2}, FileRange{{3, 2}, {7, 8}}, + [](Optional Node) { + EXPECT_TRUE(Node); + EXPECT_EQ(Node->Children.size(), 1u); + const auto &Fn = checkNode( + Node->Children[0], SourceSelectionKind::ContainsSelection, + /*NumChildren=*/1, /*Name=*/"f"); + const auto &Body = checkNode( + Fn.Children[0], SourceSelectionKind::ContainsSelection, + /*NumChildren=*/3); + checkNode(Body.Children[0], + SourceSelectionKind::InsideSelection, + /*NumChildren=*/3); + checkNode(Body.Children[1], + SourceSelectionKind::InsideSelection, + /*NumChildren=*/2); + checkNode(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( - Node->Children[0], SourceSelectionKind::ContainsSelection, - /*NumChildren=*/1, /*Name=*/"f"); - const auto &Body = checkNode( - Fn.Children[0], SourceSelectionKind::ContainsSelection, - /*NumChildren=*/4); - checkNode(Body.Children[0], - SourceSelectionKind::ContainsSelectionStart, - /*NumChildren=*/1); - checkNode(Body.Children[1], SourceSelectionKind::InsideSelection, - /*NumChildren=*/3); - checkNode(Body.Children[2], SourceSelectionKind::InsideSelection, - /*NumChildren=*/2); - checkNode(Body.Children[3], - SourceSelectionKind::ContainsSelectionEnd, - /*NumChildren=*/1); - } + findSelectedASTNodes( + Source, {2, 10}, FileRange{{2, 10}, {7, 5}}, + [](Optional Node) { + EXPECT_TRUE(Node); + EXPECT_EQ(Node->Children.size(), 1u); + const auto &Fn = checkNode( + Node->Children[0], SourceSelectionKind::ContainsSelection, + /*NumChildren=*/1, /*Name=*/"f"); + const auto &Body = checkNode( + Fn.Children[0], SourceSelectionKind::ContainsSelection, + /*NumChildren=*/4); + checkNode(Body.Children[0], + SourceSelectionKind::ContainsSelectionStart, + /*NumChildren=*/1); + checkNode(Body.Children[1], + SourceSelectionKind::InsideSelection, + /*NumChildren=*/3); + checkNode(Body.Children[2], + SourceSelectionKind::InsideSelection, + /*NumChildren=*/2); + checkNode(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( - Node->Children[0], SourceSelectionKind::ContainsSelection, - /*NumChildren=*/1, /*Name=*/"I"); - const auto &Fn = checkNode( - Impl.Children[0], SourceSelectionKind::ContainsSelection, - /*NumChildren=*/1, /*Name=*/"selected"); - allChildrenOf(Fn).shouldHaveSelectionKind( - SourceSelectionKind::ContainsSelection); - } + findSelectedASTNodes( + Source, {9, 10}, FileRange{{9, 10}, {9, 11}}, + [](Optional Node) { + EXPECT_TRUE(Node); + EXPECT_EQ(Node->Children.size(), 1u); + const auto &Impl = checkNode( + Node->Children[0], SourceSelectionKind::ContainsSelection, + /*NumChildren=*/1, /*Name=*/"I"); + const auto &Fn = checkNode( + 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( - Node->Children[0], SourceSelectionKind::ContainsSelection, - /*NumChildren=*/1, /*Name=*/"Cat"); - const auto &Fn = checkNode( - Impl.Children[0], SourceSelectionKind::ContainsSelection, - /*NumChildren=*/1, /*Name=*/"catF"); - allChildrenOf(Fn).shouldHaveSelectionKind( - SourceSelectionKind::ContainsSelection); - } + findSelectedASTNodes( + Source, {15, 1}, FileRange{{15, 1}, {15, 16}}, + [](Optional Node) { + EXPECT_TRUE(Node); + EXPECT_EQ(Node->Children.size(), 1u); + const auto &Impl = checkNode( + Node->Children[0], SourceSelectionKind::ContainsSelection, + /*NumChildren=*/1, /*Name=*/"Cat"); + const auto &Fn = checkNode( + 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( - Node->Children[0], SourceSelectionKind::ContainsSelectionStart, - /*NumChildren=*/1, /*Name=*/"I"); - const auto &Selected = checkNode( - Impl.Children[0], SourceSelectionKind::InsideSelection, - /*NumChildren=*/2, /*Name=*/"selected"); - allChildrenOf(Selected).shouldHaveSelectionKind( - SourceSelectionKind::InsideSelection); - const auto &Cat = checkNode( - Node->Children[1], SourceSelectionKind::ContainsSelectionEnd, - /*NumChildren=*/1, /*Name=*/"Cat"); - const auto &CatF = checkNode( - Cat.Children[0], SourceSelectionKind::InsideSelection, - /*NumChildren=*/1, /*Name=*/"catF"); - allChildrenOf(CatF).shouldHaveSelectionKind( - SourceSelectionKind::InsideSelection); - } + findSelectedASTNodes( + Source, {16, 1}, FileRange{{7, 1}, {16, 1}}, + [](Optional Node) { + EXPECT_TRUE(Node); + EXPECT_EQ(Node->Children.size(), 2u); + const auto &Impl = checkNode( + Node->Children[0], SourceSelectionKind::ContainsSelectionStart, + /*NumChildren=*/1, /*Name=*/"I"); + const auto &Selected = checkNode( + Impl.Children[0], SourceSelectionKind::InsideSelection, + /*NumChildren=*/2, /*Name=*/"selected"); + allChildrenOf(Selected).shouldHaveSelectionKind( + SourceSelectionKind::InsideSelection); + const auto &Cat = checkNode( + Node->Children[1], SourceSelectionKind::ContainsSelectionEnd, + /*NumChildren=*/1, /*Name=*/"Cat"); + const auto &CatF = checkNode( + 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(Node->Children[0], - SourceSelectionKind::ContainsSelection, - /*NumChildren=*/1, /*Name=*/"outerFunction"); - } + findSelectedASTNodes(Source, {19, 1}, FileRange{{19, 1}, {19, 25}}, + [](Optional Node) { + EXPECT_TRUE(Node); + EXPECT_EQ(Node->Children.size(), 1u); + checkNode( + 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( - Node->Children[0], SourceSelectionKind::ContainsSelection, - /*NumChildren=*/1, /*Name=*/"I"); - checkNode(Impl.Children[0], - SourceSelectionKind::ContainsSelection, - /*NumChildren=*/1, /*Name=*/"selected"); - } + findSelectedASTNodes( + Source, {6, 1}, FileRange{{6, 1}, {7, 2}}, + [](Optional Node) { + EXPECT_TRUE(Node); + EXPECT_EQ(Node->Children.size(), 1u); + const auto &Impl = checkNode( + Node->Children[0], SourceSelectionKind::ContainsSelection, + /*NumChildren=*/1, /*Name=*/"I"); + checkNode(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( - Node->Children[0], SourceSelectionKind::InsideSelection, - /*NumChildren=*/1, /*Name=*/"Copy"); - checkNode(Record.Children[0], - SourceSelectionKind::InsideSelection); + findSelectedASTNodes( + Source, {2, 1}, FileRange{{2, 1}, {4, 3}}, + [](Optional Node) { + EXPECT_TRUE(Node); + EXPECT_EQ(Node->Children.size(), 1u); + const auto &Record = checkNode( + Node->Children[0], SourceSelectionKind::InsideSelection, + /*NumChildren=*/1, /*Name=*/"Copy"); + checkNode(Record.Children[0], + SourceSelectionKind::InsideSelection); + }); } } // end anonymous namespace