[Syntax] Unset IsOriginal flag on nodes removed from the tree
authorIlya Biryukov <ibiryukov@google.com>
Tue, 14 Jan 2020 11:34:00 +0000 (12:34 +0100)
committerIlya Biryukov <ibiryukov@google.com>
Tue, 14 Jan 2020 16:00:33 +0000 (17:00 +0100)
And add a corresponding test.
Only nodes inside the TranslationUnit subtree can be marked as original,
computeReplacements() relies on this.

clang/lib/Tooling/Syntax/Tree.cpp
clang/unittests/Tooling/Syntax/TreeTest.cpp

index 5282857df5a9e899b624f76b81975d4578159d31..9f028c0be3b4cbfbe6998b1ce1e1d05eddcee5f9 100644 (file)
 
 using namespace clang;
 
+namespace {
+static void traverse(const syntax::Node *N,
+                     llvm::function_ref<void(const syntax::Node *)> Visit) {
+  if (auto *T = dyn_cast<syntax::Tree>(N)) {
+    for (auto *C = T->firstChild(); C; C = C->nextSibling())
+      traverse(C, Visit);
+  }
+  Visit(N);
+}
+static void traverse(syntax::Node *N,
+                     llvm::function_ref<void(syntax::Node *)> Visit) {
+  traverse(static_cast<const syntax::Node *>(N), [&](const syntax::Node *N) {
+    Visit(const_cast<syntax::Node *>(N));
+  });
+};
+} // namespace
+
 syntax::Arena::Arena(SourceManager &SourceMgr, const LangOptions &LangOpts,
                      TokenBuffer Tokens)
     : SourceMgr(SourceMgr), LangOpts(LangOpts), Tokens(std::move(Tokens)) {}
@@ -80,6 +97,8 @@ void syntax::Tree::replaceChildRangeLowLevel(Node *BeforeBegin, Node *End,
     N->Role = static_cast<unsigned>(NodeRole::Detached);
     N->Parent = nullptr;
     N->NextSibling = nullptr;
+    if (N->Original)
+      traverse(N, [&](Node *C) { C->Original = false; });
 
     N = Next;
   }
@@ -105,14 +124,6 @@ void syntax::Tree::replaceChildRangeLowLevel(Node *BeforeBegin, Node *End,
 }
 
 namespace {
-static void traverse(const syntax::Node *N,
-                     llvm::function_ref<void(const syntax::Node *)> Visit) {
-  if (auto *T = dyn_cast<syntax::Tree>(N)) {
-    for (auto *C = T->firstChild(); C; C = C->nextSibling())
-      traverse(C, Visit);
-  }
-  Visit(N);
-}
 static void dumpTokens(llvm::raw_ostream &OS, ArrayRef<syntax::Token> Tokens,
                        const SourceManager &SM) {
   assert(!Tokens.empty());
index c457c78881241c93a49f719db6463960f60313d0..42d77d893536424b964d3ec503feb33408cbee68 100644 (file)
@@ -895,6 +895,9 @@ TEST_F(SyntaxTreeTest, Mutations) {
     auto *S = cast<syntax::Statement>(nodeByRange(Input.range(), TU));
     ASSERT_TRUE(S->canModify()) << "cannot remove a statement";
     syntax::removeStatement(*Arena, S);
+    EXPECT_TRUE(S->isDetached());
+    EXPECT_FALSE(S->isOriginal())
+        << "node removed from tree cannot be marked as original";
   };
 
   std::vector<std::pair<std::string /*Input*/, std::string /*Expected*/>>