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/D88034

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

Index: clang/unittests/Tooling/Syntax/SynthesisTest.cpp
===================================================================
--- clang/unittests/Tooling/Syntax/SynthesisTest.cpp
+++ clang/unittests/Tooling/Syntax/SynthesisTest.cpp
@@ -217,7 +217,53 @@
                                  GetParam());
 
   auto *Copy = deepCopy(*Arena, OriginalTree);
-  EXPECT_TRUE(Copy == nullptr);
+  EXPECT_EQ(Copy, nullptr);
+}
+
+TEST_P(SynthesisTest, DeepCopy_MacroExpanding) {
+  auto *OriginalTree = buildTree(R"cpp(
+#define HALF_IF if (1+
+#define HALF_IF_2 1) {}
+void test() {
+  HALF_IF HALF_IF_2 else {}
+})cpp",
+                                 GetParam());
+
+  auto *Copy = deepCopyExpandingMacros(*Arena, OriginalTree);
+
+  // The syntax tree stores expanded Tokens already, as a result we can only see
+  // the macro expansion when computing replacements. The dump does show that
+  // nodes are `modifiable` now.
+  EXPECT_TRUE(treeDumpEqual(Copy, R"txt(
+TranslationUnit Detached synthesized
+`-SimpleDeclaration synthesized
+  |-'void' synthesized
+  |-SimpleDeclarator Declarator synthesized
+  | |-'test' synthesized
+  | `-ParametersAndQualifiers synthesized
+  |   |-'(' OpenParen synthesized
+  |   `-')' CloseParen synthesized
+  `-CompoundStatement synthesized
+    |-'{' OpenParen synthesized
+    |-IfStatement Statement synthesized
+    | |-'if' IntroducerKeyword synthesized
+    | |-'(' synthesized
+    | |-BinaryOperatorExpression synthesized
+    | | |-IntegerLiteralExpression LeftHandSide synthesized
+    | | | `-'1' LiteralToken synthesized
+    | | |-'+' OperatorToken synthesized
+    | | `-IntegerLiteralExpression RightHandSide synthesized
+    | |   `-'1' LiteralToken synthesized
+    | |-')' synthesized
+    | |-CompoundStatement ThenStatement synthesized
+    | | |-'{' OpenParen synthesized
+    | | `-'}' CloseParen synthesized
+    | |-'else' ElseKeyword synthesized
+    | `-CompoundStatement ElseStatement synthesized
+    |   |-'{' OpenParen synthesized
+    |   `-'}' CloseParen synthesized
+    `-'}' CloseParen synthesized
+  )txt"));
 }
 
 TEST_P(SynthesisTest, Statement_EmptyStatement) {
Index: clang/lib/Tooling/Syntax/Synthesis.cpp
===================================================================
--- clang/lib/Tooling/Syntax/Synthesis.cpp
+++ clang/lib/Tooling/Syntax/Synthesis.cpp
@@ -218,8 +218,13 @@
   return true;
 }
 
-syntax::Node *deepCopyImpl(syntax::Arena &A, const syntax::Node *N) {
+} // namespace
+
+syntax::Node *clang::syntax::deepCopyExpandingMacros(syntax::Arena &A,
+                                                     const syntax::Node *N) {
   if (const auto *L = dyn_cast<syntax::Leaf>(N))
+    // For original nodes `L->getToken()` gives us the expanded token,
+    // thus we implicitly expand any macros here.
     return createLeaf(A, L->getToken()->kind(),
                       L->getToken()->text(A.getSourceManager()));
 
@@ -227,17 +232,16 @@
   std::vector<std::pair<syntax::Node *, syntax::NodeRole>> Children;
   for (const auto *Child = T->getFirstChild(); Child;
        Child = Child->getNextSibling())
-    Children.push_back({deepCopyImpl(A, Child), Child->getRole()});
+    Children.push_back({deepCopyExpandingMacros(A, Child), Child->getRole()});
 
   return createTree(A, Children, N->getKind());
 }
-} // namespace
 
 syntax::Node *clang::syntax::deepCopy(syntax::Arena &A, const Node *N) {
   if (!canModifyAllDescendants(N))
     return nullptr;
 
-  return deepCopyImpl(A, N);
+  return deepCopyExpandingMacros(A, N);
 }
 
 syntax::EmptyStatement *clang::syntax::createEmptyStatement(syntax::Arena &A) {
Index: clang/include/clang/Tooling/Syntax/BuildTree.h
===================================================================
--- clang/include/clang/Tooling/Syntax/BuildTree.h
+++ clang/include/clang/Tooling/Syntax/BuildTree.h
@@ -56,6 +56,16 @@
 /// unmodifiable returns `nullptr`.
 syntax::Node *deepCopy(syntax::Arena &A, const syntax::Node *N);
 
+/// Creates a completely independent copy of `N` with its macros expanded.
+///
+/// Like `deepCopy` the copy is:
+/// * Detached, i.e. `Parent == NextSibling == nullptr` and
+/// `Role == Detached`.
+/// * Synthesized, i.e. `Original == false`.
+///
+/// However, `N` might have descendants coming from macros, in this case those
+/// macros are expanded.
+syntax::Node *deepCopyExpandingMacros(syntax::Arena &A, const syntax::Node *N);
 } // namespace syntax
 } // namespace clang
 #endif
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to