r361117 - Add a Visit overload for DynTypedNode to ASTNodeTraverser

Stephen Kelly via cfe-commits cfe-commits at lists.llvm.org
Sun May 19 06:03:49 PDT 2019


Author: steveire
Date: Sun May 19 06:03:48 2019
New Revision: 361117

URL: http://llvm.org/viewvc/llvm-project?rev=361117&view=rev
Log:
Add a Visit overload for DynTypedNode to ASTNodeTraverser

Reviewers: aaron.ballman

Subscribers: cfe-commits

Tags: #clang

Differential Revision: https://reviews.llvm.org/D61834

Added:
    cfe/trunk/unittests/AST/ASTTraverserTest.cpp
Modified:
    cfe/trunk/include/clang/AST/ASTNodeTraverser.h
    cfe/trunk/unittests/AST/CMakeLists.txt

Modified: cfe/trunk/include/clang/AST/ASTNodeTraverser.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTNodeTraverser.h?rev=361117&r1=361116&r2=361117&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/ASTNodeTraverser.h (original)
+++ cfe/trunk/include/clang/AST/ASTNodeTraverser.h Sun May 19 06:03:48 2019
@@ -205,6 +205,24 @@ public:
     });
   }
 
+  void Visit(const ast_type_traits::DynTypedNode &N) {
+    // FIXME: Improve this with a switch or a visitor pattern.
+    if (const auto *D = N.get<Decl>())
+      Visit(D);
+    else if (const auto *S = N.get<Stmt>())
+      Visit(S);
+    else if (const auto *QT = N.get<QualType>())
+      Visit(*QT);
+    else if (const auto *T = N.get<Type>())
+      Visit(T);
+    else if (const auto *C = N.get<CXXCtorInitializer>())
+      Visit(C);
+    else if (const auto *C = N.get<OMPClause>())
+      Visit(C);
+    else if (const auto *T = N.get<TemplateArgument>())
+      Visit(*T);
+  }
+
   void dumpDeclContext(const DeclContext *DC) {
     if (!DC)
       return;

Added: cfe/trunk/unittests/AST/ASTTraverserTest.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/AST/ASTTraverserTest.cpp?rev=361117&view=auto
==============================================================================
--- cfe/trunk/unittests/AST/ASTTraverserTest.cpp (added)
+++ cfe/trunk/unittests/AST/ASTTraverserTest.cpp Sun May 19 06:03:48 2019
@@ -0,0 +1,224 @@
+//===- unittests/AST/ASTTraverserTest.h------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/ASTNodeTraverser.h"
+#include "clang/AST/TextNodeDumper.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/Tooling/Tooling.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+using namespace clang::tooling;
+using namespace clang::ast_matchers;
+
+namespace clang {
+
+class NodeTreePrinter : public TextTreeStructure {
+  llvm::raw_ostream &OS;
+
+public:
+  NodeTreePrinter(llvm::raw_ostream &OS)
+      : TextTreeStructure(OS, /* showColors */ false), OS(OS) {}
+
+  void Visit(const Decl *D) { OS << D->getDeclKindName() << "Decl"; }
+
+  void Visit(const Stmt *S) { OS << S->getStmtClassName(); }
+
+  void Visit(QualType QT) {
+    OS << "QualType " << QT.split().Quals.getAsString();
+  }
+
+  void Visit(const Type *T) { OS << T->getTypeClassName() << "Type"; }
+
+  void Visit(const comments::Comment *C, const comments::FullComment *FC) {
+    OS << C->getCommentKindName();
+  }
+
+  void Visit(const CXXCtorInitializer *Init) { OS << "CXXCtorInitializer"; }
+
+  void Visit(const Attr *A) {
+    switch (A->getKind()) {
+#define ATTR(X)                                                                \
+  case attr::X:                                                                \
+    OS << #X;                                                                  \
+    break;
+#include "clang/Basic/AttrList.inc"
+    }
+    OS << "Attr";
+  }
+
+  void Visit(const OMPClause *C) { OS << "OMPClause"; }
+  void Visit(const TemplateArgument &A, SourceRange R = {},
+             const Decl *From = nullptr, const char *Label = nullptr) {
+    OS << "TemplateArgument";
+  }
+
+  template <typename... T> void Visit(T...) {}
+};
+
+class TestASTDumper : public ASTNodeTraverser<TestASTDumper, NodeTreePrinter> {
+
+  NodeTreePrinter MyNodeRecorder;
+
+public:
+  TestASTDumper(llvm::raw_ostream &OS) : MyNodeRecorder(OS) {}
+  NodeTreePrinter &doGetNodeDelegate() { return MyNodeRecorder; }
+};
+
+template <typename... NodeType> std::string dumpASTString(NodeType &&... N) {
+  std::string Buffer;
+  llvm::raw_string_ostream OS(Buffer);
+
+  TestASTDumper Dumper(OS);
+
+  OS << "\n";
+
+  Dumper.Visit(std::forward<NodeType &&>(N)...);
+
+  return OS.str();
+}
+
+const FunctionDecl *getFunctionNode(clang::ASTUnit *AST,
+                                    const std::string &Name) {
+  auto Result = ast_matchers::match(functionDecl(hasName(Name)).bind("fn"),
+                                    AST->getASTContext());
+  EXPECT_EQ(Result.size(), 1u);
+  return Result[0].getNodeAs<FunctionDecl>("fn");
+}
+
+template <typename T> struct Verifier {
+  static void withDynNode(T Node, const std::string &DumpString) {
+    EXPECT_EQ(dumpASTString(ast_type_traits::DynTypedNode::create(Node)),
+              DumpString);
+  }
+};
+
+template <typename T> struct Verifier<T *> {
+  static void withDynNode(T *Node, const std::string &DumpString) {
+    EXPECT_EQ(dumpASTString(ast_type_traits::DynTypedNode::create(*Node)),
+              DumpString);
+  }
+};
+
+template <typename T>
+void verifyWithDynNode(T Node, const std::string &DumpString) {
+  EXPECT_EQ(dumpASTString(Node), DumpString);
+
+  Verifier<T>::withDynNode(Node, DumpString);
+}
+
+TEST(Traverse, Dump) {
+
+  auto AST = buildASTFromCode(R"cpp(
+struct A {
+  int m_number;
+
+  /// CTor
+  A() : m_number(42) {}
+
+  [[nodiscard]] const int func() {
+    return 42;
+  }
+
+};
+
+template<typename T>
+struct templ
+{ 
+};
+
+template<>
+struct templ<int>
+{ 
+};
+
+)cpp");
+
+  const FunctionDecl *Func = getFunctionNode(AST.get(), "func");
+
+  verifyWithDynNode(Func,
+                    R"cpp(
+CXXMethodDecl
+|-CompoundStmt
+| `-ReturnStmt
+|   `-IntegerLiteral
+`-WarnUnusedResultAttr
+)cpp");
+
+  Stmt *Body = Func->getBody();
+
+  verifyWithDynNode(Body,
+                    R"cpp(
+CompoundStmt
+`-ReturnStmt
+  `-IntegerLiteral
+)cpp");
+
+  QualType QT = Func->getType();
+
+  verifyWithDynNode(QT,
+                    R"cpp(
+FunctionProtoType
+`-QualType const
+  `-BuiltinType
+)cpp");
+
+  const FunctionDecl *CTorFunc = getFunctionNode(AST.get(), "A");
+
+  verifyWithDynNode(CTorFunc->getType(),
+                    R"cpp(
+FunctionProtoType
+`-BuiltinType
+)cpp");
+
+  Attr *A = *Func->attr_begin();
+
+  {
+    std::string expectedString = R"cpp(
+WarnUnusedResultAttr
+)cpp";
+
+    EXPECT_EQ(dumpASTString(A), expectedString);
+  }
+
+  auto *CTor = dyn_cast<CXXConstructorDecl>(CTorFunc);
+  const CXXCtorInitializer *Init = *CTor->init_begin();
+
+  verifyWithDynNode(Init,
+                    R"cpp(
+CXXCtorInitializer
+`-IntegerLiteral
+)cpp");
+
+  const comments::FullComment *Comment =
+      AST->getASTContext().getLocalCommentForDeclUncached(CTorFunc);
+  {
+    std::string expectedString = R"cpp(
+FullComment
+`-ParagraphComment
+  `-TextComment
+)cpp";
+    EXPECT_EQ(dumpASTString(Comment, Comment), expectedString);
+  }
+
+  auto Result = ast_matchers::match(
+      classTemplateSpecializationDecl(hasName("templ")).bind("fn"),
+      AST->getASTContext());
+  EXPECT_EQ(Result.size(), 1u);
+  auto Templ = Result[0].getNodeAs<ClassTemplateSpecializationDecl>("fn");
+
+  TemplateArgument TA = Templ->getTemplateArgs()[0];
+
+  verifyWithDynNode(TA,
+                    R"cpp(
+TemplateArgument
+)cpp");
+}
+} // namespace clang

Modified: cfe/trunk/unittests/AST/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/AST/CMakeLists.txt?rev=361117&r1=361116&r2=361117&view=diff
==============================================================================
--- cfe/trunk/unittests/AST/CMakeLists.txt (original)
+++ cfe/trunk/unittests/AST/CMakeLists.txt Sun May 19 06:03:48 2019
@@ -12,6 +12,7 @@ add_clang_unittest(ASTTests
   ASTImporterTest.cpp
   ASTImporterGenericRedeclTest.cpp
   ASTImporterVisibilityTest.cpp
+  ASTTraverserTest.cpp
   ASTTypeTraitsTest.cpp
   ASTVectorTest.cpp
   CommentLexer.cpp




More information about the cfe-commits mailing list