[PATCH] D89794: [SyntaxTree] Implement "by-pointer output parameter to return value" refactoring.

2020-10-28 Thread Eduardo Caldas via Phabricator via cfe-commits
eduucaldas added a subscriber: sammccall.
eduucaldas added a comment.

Sam, this patch is outdated, as we're still making decisions on 
https://reviews.llvm.org/D90161 and we haven't yet landed 
https://reviews.llvm.org/D90240, please don't bother reviewing it.

This is where we started thinking about iterators on lists, and about the 
usefulness of having reverse links for syntax nodes.

I have added you to the subscriber list so you can follow the discussion once 
this is unblocked, and to show you the Mutations API in its early steps.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D89794/new/

https://reviews.llvm.org/D89794

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D89794: [SyntaxTree] Implement "by-pointer output parameter to return value" refactoring.

2020-10-28 Thread Eduardo Caldas via Phabricator via cfe-commits
eduucaldas added a subscriber: gribozavr2.
eduucaldas added a comment.

This patch will build upon https://reviews.llvm.org/D90240 and 
https://reviews.llvm.org/D90161
When those patches land, work on this patch will resume. 
It is here to illustrate the relevance of the previous patches and the general 
direction we're going.

Glad to see that you're interested David, we'll keep you updated.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D89794/new/

https://reviews.llvm.org/D89794

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D89794: [SyntaxTree] Implement "by-pointer output parameter to return value" refactoring.

2020-10-27 Thread David Blaikie via Phabricator via cfe-commits
dblaikie added a comment.

I imagine test coverage would be handy (I'm probably not the right reviewer for 
this in general, but was/am curious to see how it goes - you might want to 
search for other contributors/reviewers to the code you're changing and 
request/add them as reviewers for this patch)


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D89794/new/

https://reviews.llvm.org/D89794

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D89794: [SyntaxTree] Implement "by-pointer output parameter to return value" refactoring.

2020-10-20 Thread Eduardo Caldas via Phabricator via cfe-commits
eduucaldas created this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.
eduucaldas requested review of this revision.

Example of such refactoring:

  Customer* C;
  getCustumer(C);

  Customer C = getCustumer();


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D89794

Files:
  clang/include/clang/Tooling/Syntax/Mutations.h
  clang/lib/Tooling/Syntax/Mutations.cpp

Index: clang/lib/Tooling/Syntax/Mutations.cpp
===
--- clang/lib/Tooling/Syntax/Mutations.cpp
+++ clang/lib/Tooling/Syntax/Mutations.cpp
@@ -85,6 +85,92 @@
 P->assertInvariants();
 N->assertInvariants();
   }
+
+  static void
+  replaceChildRange(syntax::Tree *Parent, syntax::Node *BeforeBegin,
+syntax::Node *End,
+ArrayRef> NewRange) {
+if (NewRange.empty())
+  return Parent->replaceChildRangeLowLevel(BeforeBegin, End, nullptr);
+
+for (const auto  : NewRange)
+  NodeAndRole.first->setRole(NodeAndRole.second);
+
+for (auto It = NewRange.begin(), EndIt = std::prev(NewRange.end());
+ It != EndIt; ++It) {
+  auto *Node = It->first;
+  auto *Next = std::next(It)->first;
+  Node->NextSibling = Next;
+}
+
+Parent->replaceChildRangeLowLevel(BeforeBegin, End, NewRange.front().first);
+  }
+
+  /// Removes all the `Node`s between the iterators `BeforeBegin` and `End`. For
+  /// separated lists, if we remove the last element we may need to remove the
+  /// delimiter before it, in order to keep it a separated list.
+  static void removeElementAndDelimiterRange(
+  List::ElementAndDelimiterIterator BeforeBegin,
+  List::ElementAndDelimiterIterator End) {
+auto *EndNode = []() -> Node * {
+  if (End.isEnd())
+return nullptr;
+  if ((*End).element)
+return (*End).element;
+  return (*End).delimiter;
+}();
+auto *Parent = End.getParent();
+Node *BeforeBeginNode;
+if (End.isEnd() &&
+Parent->getTerminationKind() == List::TerminationKind::Separated) {
+  // In this case we also remove the delimiter before the last element of
+  // the list, if it exists.
+  if (BeforeBegin.isBeforeBegin())
+BeforeBeginNode = nullptr;
+  else if ((*BeforeBegin).element)
+BeforeBeginNode = (*BeforeBegin).element;
+  else if ((*BeforeBegin).delimiter)
+BeforeBeginNode = findPrevious((*BeforeBegin).delimiter);
+  else
+// `BeforeBegin` = (null, null) and thus we are in the last element of
+// the list. Nothing will be removed.
+return;
+} else
+  BeforeBeginNode = []() -> Node * {
+if (BeforeBegin.isBeforeBegin())
+  return nullptr;
+if ((*BeforeBegin).delimiter)
+  return (*BeforeBegin).delimiter;
+if ((*BeforeBegin).element)
+  return (*BeforeBegin).element;
+llvm_unreachable("(null, null) can only appear in the end of a "
+ "separated range, and this is not possible here");
+  }();
+
+Parent->replaceChildRangeLowLevel(BeforeBeginNode, EndNode, nullptr);
+  }
+
+  static Node *extractLastElementAndDelimiter(List *Parent) {
+auto Prev = [](List::ElementAndDelimiterIterator EDI,
+   unsigned i = 1) {
+  auto Previous = EDI.getParent()->getElementAndDelimiterBeforeBegin();
+  auto It = Previous;
+  for (unsigned j = 0; j < i; ++j)
+++It;
+  for (; It != EDI; ++It)
+++Previous;
+
+  return Previous;
+};
+if (Parent->getElementAndDelimiterBegin() ==
+Parent->getElementAndDelimiterEnd())
+  return nullptr;
+auto BeforeLast = Prev(Parent->getElementAndDelimiterEnd(), 2);
+auto Last = std::next(BeforeLast);
+removeElementAndDelimiterRange(BeforeLast,
+   Parent->getElementAndDelimiterEnd());
+return (*Last).element;
+  }
 };
 
 void syntax::removeStatement(syntax::Arena , syntax::Statement *S) {
@@ -102,3 +188,39 @@
 
   MutationsImpl::replace(S, createEmptyStatement(A));
 }
+
+void syntax::replaceOutputParameterWithReturnValue(syntax::Arena ,
+   syntax::CallExpression *CE) {
+  assert(CE);
+  assert(CE->canModify());
+  assert(CE->getParent());
+
+  // Extract Output Parameter
+  auto *OutParam =
+  MutationsImpl::extractLastElementAndDelimiter(CE->getArguments());
+
+  // Create pointer dereference with outParam
+  auto *DerefOutParam =
+  createTree(A,
+ {{createLeaf(A, tok::star), NodeRole::OperatorToken},
+  {OutParam, NodeRole::Operand}},
+ NodeKind::PrefixUnaryOperatorExpression);
+
+  // f(); -> *outParam = f();
+  // TODO: How to improve this: Add parent to AddAfter. Or `NodeIterator`, with
+  // a pointer to Parent when it's a sentinel.
+  auto *Parent = CE->getParent();
+  auto *BeforeBegin = findPrevious(CE);
+