[PATCH] D87925: [Synthesis] Fix: `createTree` only from children that are not backed by source code

Eduardo Caldas via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Fri Sep 18 11:45:52 PDT 2020


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,


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D87925.292859.patch
Type: text/x-patch
Size: 2327 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20200918/c6ae80dc/attachment.bin>


More information about the cfe-commits mailing list