eduucaldas created this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.
eduucaldas requested review of this revision.

Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D87925

Files:
  clang/include/clang/Tooling/Syntax/BuildTree.h
  clang/lib/Tooling/Syntax/Synthesis.cpp


Index: clang/lib/Tooling/Syntax/Synthesis.cpp
===================================================================
--- clang/lib/Tooling/Syntax/Synthesis.cpp
+++ clang/lib/Tooling/Syntax/Synthesis.cpp
@@ -8,6 +8,7 @@
 #include "clang/Basic/TokenKinds.h"
 #include "clang/Tooling/Syntax/BuildTree.h"
 #include "clang/Tooling/Syntax/Tree.h"
+#include <algorithm>
 
 using namespace clang;
 
@@ -184,12 +185,48 @@
   }
   llvm_unreachable("unknown node kind");
 }
+
+bool canModifyAllDescendants(const syntax::Node *N) {
+  if (const auto *L = dyn_cast<syntax::Leaf>(N))
+    return L->canModify();
+
+  const auto *T = cast<syntax::Tree>(N);
+
+  if (!T->canModify())
+    return false;
+  for (const auto *Child = T->getFirstChild(); Child;
+       Child = Child->getNextSibling())
+    if (!Child->canModify())
+      return false;
+
+  return true;
+}
+
+bool areAllSynthesized(const syntax::Node *N) {
+  if (const auto *L = dyn_cast<syntax::Leaf>(N))
+    return !L->isOriginal();
+
+  const auto *T = cast<syntax::Tree>(N);
+
+  if (T->isOriginal())
+    return false;
+  for (const auto *Child = T->getFirstChild(); Child;
+       Child = Child->getNextSibling())
+    if (Child->isOriginal())
+      return false;
+
+  return true;
+}
 } // namespace
 
 syntax::Tree *clang::syntax::createTree(
     syntax::Arena &A,
     std::vector<std::pair<syntax::Node *, syntax::NodeRole>> Children,
     syntax::NodeKind K) {
+  if (std::all_of(Children.begin(), Children.end(),
+                  [](auto p) { return areAllSynthesized(p.first); }))
+    return nullptr;
+
   auto *T = allocateTree(A, K);
   FactoryImpl::setCanModify(T);
   for (auto ChildIt = Children.rbegin(); ChildIt != Children.rend();
Index: clang/include/clang/Tooling/Syntax/BuildTree.h
===================================================================
--- clang/include/clang/Tooling/Syntax/BuildTree.h
+++ clang/include/clang/Tooling/Syntax/BuildTree.h
@@ -37,6 +37,9 @@
 // Synthesis of Trees
 /// Creates the concrete syntax node according to the specified `NodeKind` `K`.
 /// Returns it as a pointer to the base class `Tree`.
+///
+/// EXPECT: Nodes in `Children` are all synthesized, i.e. not backed by source
+/// code.
 syntax::Tree *
 createTree(syntax::Arena &A,
            std::vector<std::pair<syntax::Node *, syntax::NodeRole>> Children,


Index: clang/lib/Tooling/Syntax/Synthesis.cpp
===================================================================
--- clang/lib/Tooling/Syntax/Synthesis.cpp
+++ clang/lib/Tooling/Syntax/Synthesis.cpp
@@ -8,6 +8,7 @@
 #include "clang/Basic/TokenKinds.h"
 #include "clang/Tooling/Syntax/BuildTree.h"
 #include "clang/Tooling/Syntax/Tree.h"
+#include <algorithm>
 
 using namespace clang;
 
@@ -184,12 +185,48 @@
   }
   llvm_unreachable("unknown node kind");
 }
+
+bool canModifyAllDescendants(const syntax::Node *N) {
+  if (const auto *L = dyn_cast<syntax::Leaf>(N))
+    return L->canModify();
+
+  const auto *T = cast<syntax::Tree>(N);
+
+  if (!T->canModify())
+    return false;
+  for (const auto *Child = T->getFirstChild(); Child;
+       Child = Child->getNextSibling())
+    if (!Child->canModify())
+      return false;
+
+  return true;
+}
+
+bool areAllSynthesized(const syntax::Node *N) {
+  if (const auto *L = dyn_cast<syntax::Leaf>(N))
+    return !L->isOriginal();
+
+  const auto *T = cast<syntax::Tree>(N);
+
+  if (T->isOriginal())
+    return false;
+  for (const auto *Child = T->getFirstChild(); Child;
+       Child = Child->getNextSibling())
+    if (Child->isOriginal())
+      return false;
+
+  return true;
+}
 } // namespace
 
 syntax::Tree *clang::syntax::createTree(
     syntax::Arena &A,
     std::vector<std::pair<syntax::Node *, syntax::NodeRole>> Children,
     syntax::NodeKind K) {
+  if (std::all_of(Children.begin(), Children.end(),
+                  [](auto p) { return areAllSynthesized(p.first); }))
+    return nullptr;
+
   auto *T = allocateTree(A, K);
   FactoryImpl::setCanModify(T);
   for (auto ChildIt = Children.rbegin(); ChildIt != Children.rend();
Index: clang/include/clang/Tooling/Syntax/BuildTree.h
===================================================================
--- clang/include/clang/Tooling/Syntax/BuildTree.h
+++ clang/include/clang/Tooling/Syntax/BuildTree.h
@@ -37,6 +37,9 @@
 // Synthesis of Trees
 /// Creates the concrete syntax node according to the specified `NodeKind` `K`.
 /// Returns it as a pointer to the base class `Tree`.
+///
+/// EXPECT: Nodes in `Children` are all synthesized, i.e. not backed by source
+/// code.
 syntax::Tree *
 createTree(syntax::Arena &A,
            std::vector<std::pair<syntax::Node *, syntax::NodeRole>> Children,
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to