[cfe-commits] r162245 - in /cfe/trunk: include/clang/AST/PrettyPrinter.h lib/AST/DeclPrinter.cpp unittests/AST/CMakeLists.txt unittests/AST/DeclPrinterTest.cpp unittests/AST/Makefile

Dmitri Gribenko gribozavr at gmail.com
Mon Aug 20 16:39:06 PDT 2012


Author: gribozavr
Date: Mon Aug 20 18:39:06 2012
New Revision: 162245

URL: http://llvm.org/viewvc/llvm-project?rev=162245&view=rev
Log:
DeclPrinter: add terse output mode and lots of tests

Add a flag PrintingPolicy::DontRecurseInDeclContext to provide "terse" output
from DeclPrinter.  The motivation is to use DeclPrinter to print declarations
in user-friendly format, without overwhelming user with inner detail of the
declaration being printed.

Also add many tests for DeclPrinter.  There are quite a few things that we
print incorrectly: search for WRONG in DeclPrinterTest.cpp -- and these tests
check our output against incorrect output, so that we can fix/refactor/rewrite
the DeclPrinter later.

Added:
    cfe/trunk/unittests/AST/DeclPrinterTest.cpp
Modified:
    cfe/trunk/include/clang/AST/PrettyPrinter.h
    cfe/trunk/lib/AST/DeclPrinter.cpp
    cfe/trunk/unittests/AST/CMakeLists.txt
    cfe/trunk/unittests/AST/Makefile

Modified: cfe/trunk/include/clang/AST/PrettyPrinter.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/PrettyPrinter.h?rev=162245&r1=162244&r2=162245&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/PrettyPrinter.h (original)
+++ cfe/trunk/include/clang/AST/PrettyPrinter.h Mon Aug 20 18:39:06 2012
@@ -39,7 +39,7 @@
       SuppressUnwrittenScope(false), SuppressInitializers(false),
       ConstantArraySizeAsWritten(false), AnonymousTagLocations(true),
       SuppressStrongLifetime(false), Bool(LO.Bool),
-      DumpSourceManager(0) { }
+      DontRecurseInDeclContext(false), DumpSourceManager(0) { }
 
   /// \brief What language we're printing.
   LangOptions LangOpts;
@@ -134,6 +134,9 @@
   /// doesn't actually have 'bool' (because, e.g., it is defined as a macro).
   unsigned Bool : 1;
 
+  /// Don't print contents of DeclContexts.  Used to provide a 'terse' output.
+  unsigned DontRecurseInDeclContext : 1;
+
   /// \brief If we are "dumping" rather than "pretty-printing", this points to
   /// a SourceManager which will be used to dump SourceLocations. Dumping
   /// involves printing the internal details of the AST and pretty-printing

Modified: cfe/trunk/lib/AST/DeclPrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclPrinter.cpp?rev=162245&r1=162244&r2=162245&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclPrinter.cpp (original)
+++ cfe/trunk/lib/AST/DeclPrinter.cpp Mon Aug 20 18:39:06 2012
@@ -220,6 +220,9 @@
 //----------------------------------------------------------------------------
 
 void DeclPrinter::VisitDeclContext(DeclContext *DC, bool Indent) {
+  if (Policy.DontRecurseInDeclContext)
+    return;
+
   if (Indent)
     Indentation += Policy.Indentation;
 

Modified: cfe/trunk/unittests/AST/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/AST/CMakeLists.txt?rev=162245&r1=162244&r2=162245&view=diff
==============================================================================
--- cfe/trunk/unittests/AST/CMakeLists.txt (original)
+++ cfe/trunk/unittests/AST/CMakeLists.txt Mon Aug 20 18:39:06 2012
@@ -1,8 +1,9 @@
 add_clang_unittest(ASTTests
   CommentLexer.cpp
   CommentParser.cpp
+  DeclPrinterTest.cpp
   )
 
 target_link_libraries(ASTTests
-  clangAST
+  clangAST clangASTMatchers clangTooling
   )

Added: cfe/trunk/unittests/AST/DeclPrinterTest.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/AST/DeclPrinterTest.cpp?rev=162245&view=auto
==============================================================================
--- cfe/trunk/unittests/AST/DeclPrinterTest.cpp (added)
+++ cfe/trunk/unittests/AST/DeclPrinterTest.cpp Mon Aug 20 18:39:06 2012
@@ -0,0 +1,1200 @@
+//===- unittests/AST/DeclPrinterTest.cpp --- Declaration printer tests ----===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains tests for Decl::print() and related methods.
+//
+// Search this file for WRONG to see test cases that are producing something
+// completely wrong, invalid C++ or just misleading.
+//
+// These tests have a coding convention:
+// * declaration to be printed is named 'A' unless it should have some special
+// name (e.g., 'operator+');
+// * additional helper declarations are 'Z', 'Y', 'X' and so on.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Tooling/Tooling.h"
+#include "gtest/gtest.h"
+
+using namespace clang;
+using namespace ast_matchers;
+using namespace tooling;
+
+namespace {
+
+void PrintDecl(raw_ostream &Out, const ASTContext *Context, const Decl *D) {
+  PrintingPolicy Policy = Context->getPrintingPolicy();
+  Policy.DontRecurseInDeclContext = true;
+  D->print(Out, Policy, /*Indentation*/ 0, /*PrintInstantiation*/ false);
+}
+
+class PrintMatch : public MatchFinder::MatchCallback {
+  SmallString<1024> Printed;
+  unsigned NumFoundDecls;
+
+public:
+  PrintMatch() : NumFoundDecls(0) {}
+
+  virtual void run(const MatchFinder::MatchResult &Result) {
+    const Decl *D = Result.Nodes.getDeclAs<Decl>("id");
+    if (!D || D->isImplicit())
+      return;
+    NumFoundDecls++;
+    if (NumFoundDecls > 1)
+      return;
+
+    llvm::raw_svector_ostream Out(Printed);
+    PrintDecl(Out, Result.Context, D);
+  }
+
+  StringRef getPrinted() const {
+    return Printed;
+  }
+
+  unsigned getNumFoundDecls() const {
+    return NumFoundDecls;
+  }
+};
+
+bool runToolOnCode(clang::FrontendAction *ToolAction, const Twine &Code,
+                   ArrayRef<const char *> ClangArgs) {
+  SmallString<16> FileNameStorage;
+  StringRef FileNameRef = "input.cc";
+
+  std::vector<std::string> ArgVector;
+  ArgVector.push_back("clang-tool");
+  ArgVector.push_back("-fsyntax-only");
+  ArgVector.push_back(FileNameRef.data());
+  for (unsigned i = 0, e = ClangArgs.size(); i != e; ++i)
+    ArgVector.push_back(ClangArgs[i]);
+
+  FileManager Files((FileSystemOptions()));
+  ToolInvocation Invocation(ArgVector, ToolAction, &Files);
+
+  SmallString<1024> CodeStorage;
+  Invocation.mapVirtualFile(FileNameRef,
+                            Code.toNullTerminatedStringRef(CodeStorage));
+  return Invocation.run();
+}
+
+::testing::AssertionResult PrintedDeclMatches(
+                                  StringRef Code,
+                                  ArrayRef<const char *> ClangArgs,
+                                  const DeclarationMatcher &NodeMatch,
+                                  StringRef ExpectedPrinted) {
+  PrintMatch Printer;
+  MatchFinder Finder;
+  Finder.addMatcher(NodeMatch, &Printer);
+  OwningPtr<FrontendActionFactory> Factory(newFrontendActionFactory(&Finder));
+
+  if (!runToolOnCode(Factory->create(), Code, ClangArgs))
+    return testing::AssertionFailure() << "Parsing error in \"" << Code << "\"";
+
+  if (Printer.getNumFoundDecls() == 0)
+    return testing::AssertionFailure()
+        << "Matcher didn't find any declarations";
+
+  if (Printer.getNumFoundDecls() > 1)
+    return testing::AssertionFailure()
+        << "Matcher should match only one declaration "
+           "(found " << Printer.getNumFoundDecls() << ")";
+
+  if (Printer.getPrinted() != ExpectedPrinted)
+    return ::testing::AssertionFailure()
+      << "Expected \"" << ExpectedPrinted << "\", "
+         "got \"" << Printer.getPrinted() << "\"";
+
+  return ::testing::AssertionSuccess();
+}
+
+::testing::AssertionResult PrintedDeclMatches(StringRef Code,
+                                              StringRef DeclName,
+                                              StringRef ExpectedPrinted) {
+  return PrintedDeclMatches(Code,
+                            ArrayRef<const char *>(),
+                            nameableDeclaration(hasName(DeclName)).bind("id"),
+                            ExpectedPrinted);
+}
+
+::testing::AssertionResult PrintedDeclMatches(
+                                  StringRef Code,
+                                  const DeclarationMatcher &NodeMatch,
+                                  StringRef ExpectedPrinted) {
+  return PrintedDeclMatches(Code,
+                            ArrayRef<const char *>(),
+                            NodeMatch,
+                            ExpectedPrinted);
+}
+
+::testing::AssertionResult PrintedDeclCXX11Matches(StringRef Code,
+                                                   StringRef DeclName,
+                                                   StringRef ExpectedPrinted) {
+  return PrintedDeclMatches(Code,
+                            ArrayRef<const char *>("-std=c++11"),
+                            nameableDeclaration(hasName(DeclName)).bind("id"),
+                            ExpectedPrinted);
+}
+
+::testing::AssertionResult PrintedDeclCXX11Matches(
+                                  StringRef Code,
+                                  const DeclarationMatcher &NodeMatch,
+                                  StringRef ExpectedPrinted) {
+  return PrintedDeclMatches(Code,
+                            ArrayRef<const char *>("-std=c++11"),
+                            NodeMatch,
+                            ExpectedPrinted);
+}
+
+} // unnamed namespace
+
+TEST(DeclPrinter, TestNamespace1) {
+  ASSERT_TRUE(PrintedDeclMatches(
+    "namespace A { int B; }",
+    "A",
+    "namespace A {\n}"));
+    // Should be: with { ... }
+}
+
+TEST(DeclPrinter, TestNamespace2) {
+  ASSERT_TRUE(PrintedDeclCXX11Matches(
+    "inline namespace A { int B; }",
+    "A",
+    "inline namespace A {\n}"));
+    // Should be: with { ... }
+}
+
+TEST(DeclPrinter, TestNamespaceAlias1) {
+  ASSERT_TRUE(PrintedDeclMatches(
+    "namespace Z { }"
+    "namespace A = Z;",
+    "A",
+    "namespace A = Z"));
+    // Should be: with semicolon
+}
+
+TEST(DeclPrinter, TestNamespaceAlias2) {
+  ASSERT_TRUE(PrintedDeclMatches(
+    "namespace X { namespace Y {} }"
+    "namespace A = X::Y;",
+    "A",
+    "namespace A = X::Y"));
+    // Should be: with semicolon
+}
+
+TEST(DeclPrinter, TestCXXRecordDecl1) {
+  ASSERT_TRUE(PrintedDeclMatches(
+    "class A { int a; };",
+    "A",
+    "class A {\n}"));
+    // Should be: with semicolon, with { ... }
+}
+
+TEST(DeclPrinter, TestCXXRecordDecl2) {
+  ASSERT_TRUE(PrintedDeclMatches(
+    "struct A { int a; };",
+    "A",
+    "struct A {\n}"));
+    // Should be: with semicolon, with { ... }
+}
+
+TEST(DeclPrinter, TestCXXRecordDecl3) {
+  ASSERT_TRUE(PrintedDeclMatches(
+    "union A { int a; };",
+    "A",
+    "union A {\n}"));
+    // Should be: with semicolon, with { ... }
+}
+
+TEST(DeclPrinter, TestCXXRecordDecl4) {
+  ASSERT_TRUE(PrintedDeclMatches(
+    "class Z { int a; };"
+    "class A : Z { int b; };",
+    "A",
+    "class A :  Z {\n}"));
+    // Should be: with semicolon, with { ... }, without two spaces
+}
+
+TEST(DeclPrinter, TestCXXRecordDecl5) {
+  ASSERT_TRUE(PrintedDeclMatches(
+    "struct Z { int a; };"
+    "struct A : Z { int b; };",
+    "A",
+    "struct A :  Z {\n}"));
+    // Should be: with semicolon, with { ... }, without two spaces
+}
+
+TEST(DeclPrinter, TestCXXRecordDecl6) {
+  ASSERT_TRUE(PrintedDeclMatches(
+    "class Z { int a; };"
+    "class A : public Z { int b; };",
+    "A",
+    "class A : public Z {\n}"));
+    // Should be: with semicolon, with { ... }
+}
+
+TEST(DeclPrinter, TestCXXRecordDecl7) {
+  ASSERT_TRUE(PrintedDeclMatches(
+    "class Z { int a; };"
+    "class A : protected Z { int b; };",
+    "A",
+    "class A : protected Z {\n}"));
+    // Should be: with semicolon, with { ... }
+}
+
+TEST(DeclPrinter, TestCXXRecordDecl8) {
+  ASSERT_TRUE(PrintedDeclMatches(
+    "class Z { int a; };"
+    "class A : private Z { int b; };",
+    "A",
+    "class A : private Z {\n}"));
+    // Should be: with semicolon, with { ... }
+}
+
+TEST(DeclPrinter, TestCXXRecordDecl9) {
+  ASSERT_TRUE(PrintedDeclMatches(
+    "class Z { int a; };"
+    "class A : virtual Z { int b; };",
+    "A",
+    "class A : virtual  Z {\n}"));
+    // Should be: with semicolon, with { ... }, without two spaces
+}
+
+TEST(DeclPrinter, TestCXXRecordDecl10) {
+  ASSERT_TRUE(PrintedDeclMatches(
+    "class Z { int a; };"
+    "class A : virtual public Z { int b; };",
+    "A",
+    "class A : virtual public Z {\n}"));
+    // Should be: with semicolon, with { ... }
+}
+
+TEST(DeclPrinter, TestCXXRecordDecl11) {
+  ASSERT_TRUE(PrintedDeclMatches(
+    "class Z { int a; };"
+    "class Y : virtual public Z { int b; };"
+    "class A : virtual public Z, private Y { int c; };",
+    "A",
+    "class A : virtual public Z, private Y {\n}"));
+    // Should be: with semicolon, with { ... }
+}
+
+TEST(DeclPrinter, TestFunctionDecl1) {
+  ASSERT_TRUE(PrintedDeclMatches(
+    "void A();",
+    "A",
+    "void A()"));
+    // Should be: with semicolon
+}
+
+TEST(DeclPrinter, TestFunctionDecl2) {
+  ASSERT_TRUE(PrintedDeclMatches(
+    "extern void A();",
+    "A",
+    "extern void A()"));
+    // Should be: with semicolon
+}
+
+TEST(DeclPrinter, TestFunctionDecl3) {
+  ASSERT_TRUE(PrintedDeclMatches(
+    "static void A();",
+    "A",
+    "static void A()"));
+    // Should be: with semicolon
+}
+
+TEST(DeclPrinter, TestFunctionDecl4) {
+  ASSERT_TRUE(PrintedDeclMatches(
+    "inline void A();",
+    "A",
+    "inline void A()"));
+    // Should be: with semicolon
+}
+
+TEST(DeclPrinter, TestFunctionDecl5) {
+  ASSERT_TRUE(PrintedDeclCXX11Matches(
+    "constexpr int A(int a);",
+    "A",
+    "int A(int a)"));
+    // WRONG; Should be: "constexpr int A(int a);"
+}
+
+TEST(DeclPrinter, TestFunctionDecl6) {
+  ASSERT_TRUE(PrintedDeclMatches(
+    "void A(int a);",
+    "A",
+    "void A(int a)"));
+    // Should be: with semicolon
+}
+
+TEST(DeclPrinter, TestFunctionDecl7) {
+  ASSERT_TRUE(PrintedDeclMatches(
+    "void A(...);",
+    "A",
+    "void A(...)"));
+    // Should be: with semicolon
+}
+
+TEST(DeclPrinter, TestFunctionDecl8) {
+  ASSERT_TRUE(PrintedDeclMatches(
+    "void A(int a, ...);",
+    "A",
+    "void A(int a, ...)"));
+    // Should be: with semicolon
+}
+
+TEST(DeclPrinter, TestFunctionDecl9) {
+  ASSERT_TRUE(PrintedDeclMatches(
+    "typedef long size_t;"
+    "typedef int *pInt;"
+    "void A(int a, pInt b, size_t c);",
+    "A",
+    "void A(int a, pInt b, size_t c)"));
+    // Should be: with semicolon
+}
+
+TEST(DeclPrinter, TestFunctionDecl10) {
+  ASSERT_TRUE(PrintedDeclMatches(
+    "void A(int a, int b = 0);",
+    "A",
+    "void A(int a, int b = 0)"));
+    // Should be: with semicolon
+}
+
+TEST(DeclPrinter, TestFunctionDecl11) {
+  ASSERT_TRUE(PrintedDeclMatches(
+    "void (*A(int a))(int b);",
+    "A",
+    "void (*A(int a))(int)"));
+    // Should be: with semicolon, with parameter name (?)
+}
+
+TEST(DeclPrinter, TestFunctionDecl12) {
+  ASSERT_TRUE(PrintedDeclMatches(
+    "template<typename T>"
+    "void A(T t) { }"
+    "template<>"
+    "void A(int N) { }",
+    function(hasName("A"), isExplicitTemplateSpecialization()).bind("id"),
+    "void A(int N) {\n}\n\n"));
+    // WRONG; Should be: "template <> void A(int N);"));
+}
+
+
+TEST(DeclPrinter, TestCXXConstructorDecl1) {
+  ASSERT_TRUE(PrintedDeclMatches(
+    "struct A {"
+    "  A();"
+    "};",
+    constructor(ofClass(hasName("A"))).bind("id"),
+    ""));
+    // WRONG; Should be: "A();"
+}
+
+TEST(DeclPrinter, TestCXXConstructorDecl2) {
+  ASSERT_TRUE(PrintedDeclMatches(
+    "struct A {"
+    "  A(int a);"
+    "};",
+    constructor(ofClass(hasName("A"))).bind("id"),
+    ""));
+    // WRONG; Should be: "A(int a);"
+}
+
+TEST(DeclPrinter, TestCXXConstructorDecl3) {
+  ASSERT_TRUE(PrintedDeclMatches(
+    "struct A {"
+    "  A(const A &a);"
+    "};",
+    constructor(ofClass(hasName("A"))).bind("id"),
+    ""));
+    // WRONG; Should be: "A(const A &a);"
+}
+
+TEST(DeclPrinter, TestCXXConstructorDecl4) {
+  ASSERT_TRUE(PrintedDeclMatches(
+    "struct A {"
+    "  A(const A &a, int = 0);"
+    "};",
+    constructor(ofClass(hasName("A"))).bind("id"),
+    ""));
+    // WRONG; Should be: "A(const A &a, int = 0);"
+}
+
+TEST(DeclPrinter, TestCXXConstructorDecl5) {
+  ASSERT_TRUE(PrintedDeclCXX11Matches(
+    "struct A {"
+    "  A(const A &&a);"
+    "};",
+    constructor(ofClass(hasName("A"))).bind("id"),
+    ""));
+    // WRONG; Should be: "A(const A &&a);"
+}
+
+TEST(DeclPrinter, TestCXXConstructorDecl6) {
+  ASSERT_TRUE(PrintedDeclMatches(
+    "struct A {"
+    "  explicit A(int a);"
+    "};",
+    constructor(ofClass(hasName("A"))).bind("id"),
+    ""));
+    // WRONG; Should be: "explicit A(int a);"
+}
+
+TEST(DeclPrinter, TestCXXConstructorDecl7) {
+  ASSERT_TRUE(PrintedDeclMatches(
+    "struct A {"
+    "  constexpr A();"
+    "};",
+    ArrayRef<const char *>("-std=c++11"),
+    constructor(ofClass(hasName("A"))).bind("id"),
+    ""));
+    // WRONG; Should be: "constexpr A();"
+}
+
+TEST(DeclPrinter, TestCXXConstructorDecl8) {
+  ASSERT_TRUE(PrintedDeclMatches(
+    "struct A {"
+    "  A() = default;"
+    "};",
+    ArrayRef<const char *>("-std=c++11"),
+    constructor(ofClass(hasName("A"))).bind("id"),
+    ""));
+    // WRONG; Should be: "A() = default;"
+}
+
+TEST(DeclPrinter, TestCXXConstructorDecl9) {
+  ASSERT_TRUE(PrintedDeclMatches(
+    "struct A {"
+    "  A() = delete;"
+    "};",
+    ArrayRef<const char *>("-std=c++11"),
+    constructor(ofClass(hasName("A"))).bind("id"),
+    " = delete"));
+    // WRONG; Should be: "A() = delete;"
+}
+
+TEST(DeclPrinter, TestCXXDestructorDecl1) {
+  ASSERT_TRUE(PrintedDeclMatches(
+    "struct A {"
+    "  ~A();"
+    "};",
+    destructor(ofClass(hasName("A"))).bind("id"),
+    "void ~A()"));
+    // WRONG; Should be: "~A();"
+}
+
+TEST(DeclPrinter, TestCXXDestructorDecl2) {
+  ASSERT_TRUE(PrintedDeclMatches(
+    "struct A {"
+    "  virtual ~A();"
+    "};",
+    destructor(ofClass(hasName("A"))).bind("id"),
+    "virtual void ~A()"));
+    // WRONG; Should be: "virtual ~A();"
+}
+
+TEST(DeclPrinter, TestCXXConversionDecl1) {
+  ASSERT_TRUE(PrintedDeclMatches(
+    "struct A {"
+    "  operator int();"
+    "};",
+    method(ofClass(hasName("A"))).bind("id"),
+    "int operator int()"));
+    // WRONG; Should be: "operator int();"
+}
+
+TEST(DeclPrinter, TestCXXConversionDecl2) {
+  ASSERT_TRUE(PrintedDeclMatches(
+    "struct A {"
+    "  operator bool();"
+    "};",
+    method(ofClass(hasName("A"))).bind("id"),
+    "bool operator _Bool()"));
+    // WRONG; Should be: "operator bool();"
+}
+
+TEST(DeclPrinter, TestCXXConversionDecl3) {
+  ASSERT_TRUE(PrintedDeclMatches(
+    "struct Z {};"
+    "struct A {"
+    "  operator Z();"
+    "};",
+    method(ofClass(hasName("A"))).bind("id"),
+    "Z operator struct Z()"));
+    // WRONG; Should be: "operator Z();"
+}
+
+TEST(DeclPrinter, TestCXXMethodDecl_AllocationFunction1) {
+  ASSERT_TRUE(PrintedDeclMatches(
+    "namespace std { typedef decltype(sizeof(int)) size_t; }"
+    "struct Z {"
+    "  void *operator new(std::size_t);"
+    "};",
+    ArrayRef<const char *>("-std=c++11"),
+    method(ofClass(hasName("Z"))).bind("id"),
+    "void *operator new(std::size_t)"));
+    // Should be: with semicolon
+}
+
+TEST(DeclPrinter, TestCXXMethodDecl_AllocationFunction2) {
+  ASSERT_TRUE(PrintedDeclMatches(
+    "namespace std { typedef decltype(sizeof(int)) size_t; }"
+    "struct Z {"
+    "  void *operator new[](std::size_t);"
+    "};",
+    ArrayRef<const char *>("-std=c++11"),
+    method(ofClass(hasName("Z"))).bind("id"),
+    "void *operator new[](std::size_t)"));
+    // Should be: with semicolon
+}
+
+TEST(DeclPrinter, TestCXXMethodDecl_AllocationFunction3) {
+  ASSERT_TRUE(PrintedDeclMatches(
+    "struct Z {"
+    "  void operator delete(void *);"
+    "};",
+    ArrayRef<const char *>("-std=c++11"),
+    method(ofClass(hasName("Z"))).bind("id"),
+    "void operator delete(void *) noexcept"));
+    // Should be: with semicolon, without noexcept?
+}
+
+TEST(DeclPrinter, TestCXXMethodDecl_AllocationFunction4) {
+  ASSERT_TRUE(PrintedDeclMatches(
+    "struct Z {"
+    "  void operator delete(void *);"
+    "};",
+    method(ofClass(hasName("Z"))).bind("id"),
+    "void operator delete(void *)"));
+    // Should be: with semicolon
+}
+
+TEST(DeclPrinter, TestCXXMethodDecl_AllocationFunction5) {
+  ASSERT_TRUE(PrintedDeclMatches(
+    "struct Z {"
+    "  void operator delete[](void *);"
+    "};",
+    ArrayRef<const char *>("-std=c++11"),
+    method(ofClass(hasName("Z"))).bind("id"),
+    "void operator delete[](void *) noexcept"));
+    // Should be: with semicolon, without noexcept?
+}
+
+TEST(DeclPrinter, TestCXXMethodDecl_Operator1) {
+  const char *OperatorNames[] = {
+    "+",  "-",  "*",  "/",  "%",  "^",   "&",   "|",
+    "=",  "<",  ">",  "+=", "-=", "*=",  "/=",  "%=",
+    "^=", "&=", "|=", "<<", ">>", ">>=", "<<=", "==",  "!=",
+    "<=", ">=", "&&", "||",  ",", "->*",
+    "()", "[]"
+  };
+
+  for (unsigned i = 0, e = llvm::array_lengthof(OperatorNames); i != e; ++i) {
+    SmallString<128> Code;
+    Code.append("struct Z { void operator");
+    Code.append(OperatorNames[i]);
+    Code.append("(Z z); };");
+
+    SmallString<128> Expected;
+    Expected.append("void operator");
+    Expected.append(OperatorNames[i]);
+    Expected.append("(Z z)");
+    // Should be: with semicolon
+
+    ASSERT_TRUE(PrintedDeclMatches(
+      Code,
+      method(ofClass(hasName("Z"))).bind("id"),
+      Expected));
+  }
+}
+
+TEST(DeclPrinter, TestCXXMethodDecl_Operator2) {
+  const char *OperatorNames[] = {
+    "~", "!", "++", "--", "->"
+  };
+
+  for (unsigned i = 0, e = llvm::array_lengthof(OperatorNames); i != e; ++i) {
+    SmallString<128> Code;
+    Code.append("struct Z { void operator");
+    Code.append(OperatorNames[i]);
+    Code.append("(); };");
+
+    SmallString<128> Expected;
+    Expected.append("void operator");
+    Expected.append(OperatorNames[i]);
+    Expected.append("()");
+    // Should be: with semicolon
+
+    ASSERT_TRUE(PrintedDeclMatches(
+      Code,
+      method(ofClass(hasName("Z"))).bind("id"),
+      Expected));
+  }
+}
+
+TEST(DeclPrinter, TestCXXMethodDecl1) {
+  ASSERT_TRUE(PrintedDeclMatches(
+    "struct Z {"
+    "  void A(int a);"
+    "};",
+    "A",
+    "void A(int a)"));
+    // Should be: with semicolon
+}
+
+TEST(DeclPrinter, TestCXXMethodDecl2) {
+  ASSERT_TRUE(PrintedDeclMatches(
+    "struct Z {"
+    "  virtual void A(int a);"
+    "};",
+    "A",
+    "virtual void A(int a)"));
+    // Should be: with semicolon
+}
+
+TEST(DeclPrinter, TestCXXMethodDecl3) {
+  ASSERT_TRUE(PrintedDeclMatches(
+    "struct Z {"
+    "  virtual void A(int a);"
+    "};"
+    "struct ZZ : Z {"
+    "  void A(int a);"
+    "};",
+    "ZZ::A",
+    "void A(int a)"));
+    // Should be: with semicolon
+    // TODO: should we print "virtual"?
+}
+
+TEST(DeclPrinter, TestCXXMethodDecl4) {
+  ASSERT_TRUE(PrintedDeclMatches(
+    "struct Z {"
+    "  inline void A(int a);"
+    "};",
+    "A",
+    "inline void A(int a)"));
+    // Should be: with semicolon
+}
+
+TEST(DeclPrinter, TestCXXMethodDecl5) {
+  ASSERT_TRUE(PrintedDeclMatches(
+    "struct Z {"
+    "  virtual void A(int a) = 0;"
+    "};",
+    "A",
+    "virtual void A(int a) = 0"));
+    // Should be: with semicolon
+}
+
+TEST(DeclPrinter, TestCXXMethodDecl_CVQualifier1) {
+  ASSERT_TRUE(PrintedDeclMatches(
+    "struct Z {"
+    "  void A(int a) const;"
+    "};",
+    "A",
+    "void A(int a) const"));
+    // Should be: with semicolon
+}
+
+TEST(DeclPrinter, TestCXXMethodDecl_CVQualifier2) {
+  ASSERT_TRUE(PrintedDeclMatches(
+    "struct Z {"
+    "  void A(int a) volatile;"
+    "};",
+    "A",
+    "void A(int a) volatile"));
+    // Should be: with semicolon
+}
+
+TEST(DeclPrinter, TestCXXMethodDecl_CVQualifier3) {
+  ASSERT_TRUE(PrintedDeclMatches(
+    "struct Z {"
+    "  void A(int a) const volatile;"
+    "};",
+    "A",
+    "void A(int a) const volatile"));
+    // Should be: with semicolon
+}
+
+TEST(DeclPrinter, TestCXXMethodDecl_RefQualifier1) {
+  ASSERT_TRUE(PrintedDeclCXX11Matches(
+    "struct Z {"
+    "  void A(int a) &;"
+    "};",
+    "A",
+    "void A(int a)"));
+    // WRONG; Should be: "void A(int a) &;"
+}
+
+TEST(DeclPrinter, TestCXXMethodDecl_RefQualifier2) {
+  ASSERT_TRUE(PrintedDeclCXX11Matches(
+    "struct Z {"
+    "  void A(int a) &&;"
+    "};",
+    "A",
+    "void A(int a)"));
+    // WRONG; Should be: "void A(int a) &&;"
+}
+
+TEST(DeclPrinter, TestFunctionDecl_ExceptionSpecification1) {
+  ASSERT_TRUE(PrintedDeclMatches(
+    "struct Z {"
+    "  void A(int a) throw();"
+    "};",
+    "A",
+    "void A(int a) throw()"));
+    // Should be: with semicolon
+}
+
+TEST(DeclPrinter, TestFunctionDecl_ExceptionSpecification2) {
+  ASSERT_TRUE(PrintedDeclMatches(
+    "struct Z {"
+    "  void A(int a) throw(int);"
+    "};",
+    "A",
+    "void A(int a) throw(int)"));
+    // Should be: with semicolon
+}
+
+TEST(DeclPrinter, TestFunctionDecl_ExceptionSpecification3) {
+  ASSERT_TRUE(PrintedDeclMatches(
+    "class ZZ {};"
+    "struct Z {"
+    "  void A(int a) throw(ZZ, int);"
+    "};",
+    "A",
+    "void A(int a) throw(ZZ, int)"));
+    // Should be: with semicolon
+}
+
+TEST(DeclPrinter, TestFunctionDecl_ExceptionSpecification4) {
+  ASSERT_TRUE(PrintedDeclCXX11Matches(
+    "struct Z {"
+    "  void A(int a) noexcept;"
+    "};",
+    "A",
+    "void A(int a) noexcept"));
+    // Should be: with semicolon
+}
+
+TEST(DeclPrinter, TestFunctionDecl_ExceptionSpecification5) {
+  ASSERT_TRUE(PrintedDeclCXX11Matches(
+    "struct Z {"
+    "  void A(int a) noexcept(true);"
+    "};",
+    "A",
+    "void A(int a) noexcept(trueA(int a) noexcept(true)"));
+    // WRONG; Should be: "void A(int a) noexcept(true);"
+}
+
+TEST(DeclPrinter, TestFunctionDecl_ExceptionSpecification6) {
+  ASSERT_TRUE(PrintedDeclCXX11Matches(
+    "struct Z {"
+    "  void A(int a) noexcept(1 < 2);"
+    "};",
+    "A",
+    "void A(int a) noexcept(1 < 2A(int a) noexcept(1 < 2)"));
+    // WRONG; Should be: "void A(int a) noexcept(1 < 2);"
+}
+
+TEST(DeclPrinter, TestFunctionDecl_ExceptionSpecification7) {
+  ASSERT_TRUE(PrintedDeclCXX11Matches(
+    "template<int N>"
+    "struct Z {"
+    "  void A(int a) noexcept(N < 2);"
+    "};",
+    "A",
+    "void A(int a) noexcept(N < 2A(int a) noexcept(N < 2)"));
+    // WRONG; Should be: "void A(int a) noexcept(N < 2);"
+}
+
+TEST(DeclPrinter, TestVarDecl1) {
+  ASSERT_TRUE(PrintedDeclMatches(
+    "char *const (*(*A)[5])(int);",
+    "A",
+    "char *const (*(*A)[5])(int)"));
+    // Should be: with semicolon
+}
+
+TEST(DeclPrinter, TestVarDecl2) {
+  ASSERT_TRUE(PrintedDeclMatches(
+    "void (*A)() throw(int);",
+    "A",
+    "void (*A)() throw(int)"));
+    // Should be: with semicolon
+}
+
+TEST(DeclPrinter, TestVarDecl3) {
+  ASSERT_TRUE(PrintedDeclCXX11Matches(
+    "void (*A)() noexcept;",
+    "A",
+    "void (*A)() noexcept"));
+    // Should be: with semicolon
+}
+
+TEST(DeclPrinter, TestFieldDecl1) {
+  ASSERT_TRUE(PrintedDeclMatches(
+    "template<typename T>"
+    "struct Z { T A; };",
+    "A",
+    "T A"));
+    // Should be: with semicolon
+}
+
+TEST(DeclPrinter, TestFieldDecl2) {
+  ASSERT_TRUE(PrintedDeclMatches(
+    "template<int N>"
+    "struct Z { int A[N]; };",
+    "A",
+    "int A[N]"));
+    // Should be: with semicolon
+}
+
+TEST(DeclPrinter, TestClassTemplateDecl1) {
+  ASSERT_TRUE(PrintedDeclMatches(
+    "template<typename T>"
+    "struct A { T a; };",
+    classTemplate(hasName("A")).bind("id"),
+    "template <typename T> struct A {\n}"));
+    // Should be: with semicolon, with { ... }
+}
+
+TEST(DeclPrinter, TestClassTemplateDecl2) {
+  ASSERT_TRUE(PrintedDeclMatches(
+    "template<typename T = int>"
+    "struct A { T a; };",
+    classTemplate(hasName("A")).bind("id"),
+    "template <typename T = int> struct A {\n}"));
+    // Should be: with semicolon, with { ... }
+}
+
+TEST(DeclPrinter, TestClassTemplateDecl3) {
+  ASSERT_TRUE(PrintedDeclMatches(
+    "template<class T>"
+    "struct A { T a; };",
+    classTemplate(hasName("A")).bind("id"),
+    "template <class T> struct A {\n}"));
+    // Should be: with semicolon, with { ... }
+}
+
+TEST(DeclPrinter, TestClassTemplateDecl4) {
+  ASSERT_TRUE(PrintedDeclMatches(
+    "template<typename T, typename U>"
+    "struct A { T a; U b; };",
+    classTemplate(hasName("A")).bind("id"),
+    "template <typename T, typename U> struct A {\n}"));
+    // Should be: with semicolon, with { ... }
+}
+
+TEST(DeclPrinter, TestClassTemplateDecl5) {
+  ASSERT_TRUE(PrintedDeclMatches(
+    "template<int N>"
+    "struct A { int a[N]; };",
+    classTemplate(hasName("A")).bind("id"),
+    "template <int N> struct A {\n}"));
+    // Should be: with semicolon, with { ... }
+}
+
+TEST(DeclPrinter, TestClassTemplateDecl6) {
+  ASSERT_TRUE(PrintedDeclMatches(
+    "template<int N = 42>"
+    "struct A { int a[N]; };",
+    classTemplate(hasName("A")).bind("id"),
+    "template <int N = 42> struct A {\n}"));
+    // Should be: with semicolon, with { ... }
+}
+
+TEST(DeclPrinter, TestClassTemplateDecl7) {
+  ASSERT_TRUE(PrintedDeclMatches(
+    "typedef int MyInt;"
+    "template<MyInt N>"
+    "struct A { int a[N]; };",
+    classTemplate(hasName("A")).bind("id"),
+    "template <MyInt N> struct A {\n}"));
+    // Should be: with semicolon, with { ... }
+}
+
+TEST(DeclPrinter, TestClassTemplateDecl8) {
+  ASSERT_TRUE(PrintedDeclMatches(
+    "template<template<typename U> class T> struct A { };",
+    classTemplate(hasName("A")).bind("id"),
+    "template <template <typename U> class T> struct A {\n}"));
+    // Should be: with semicolon, with { ... }
+}
+
+TEST(DeclPrinter, TestClassTemplateDecl9) {
+  ASSERT_TRUE(PrintedDeclMatches(
+    "template<typename T> struct Z { };"
+    "template<template<typename U> class T = Z> struct A { };",
+    classTemplate(hasName("A")).bind("id"),
+    "template <template <typename U> class T> struct A {\n}"));
+    // Should be: with semicolon, with { ... }
+}
+
+TEST(DeclPrinter, TestClassTemplateDecl10) {
+  ASSERT_TRUE(PrintedDeclCXX11Matches(
+    "template<typename... T>"
+    "struct A { int a; };",
+    classTemplate(hasName("A")).bind("id"),
+    "template <typename ... T> struct A {\n}"));
+    // Should be: with semicolon, with { ... }, without spaces before '...'
+}
+
+TEST(DeclPrinter, TestClassTemplateDecl11) {
+  ASSERT_TRUE(PrintedDeclCXX11Matches(
+    "template<typename... T>"
+    "struct A : public T... { int a; };",
+    classTemplate(hasName("A")).bind("id"),
+    "template <typename ... T> struct A : public T... {\n}"));
+    // Should be: with semicolon, with { ... }, without spaces before '...'
+}
+
+TEST(DeclPrinter, TestClassTemplatePartialSpecializationDecl1) {
+  ASSERT_TRUE(PrintedDeclMatches(
+    "template<typename T, typename U>"
+    "struct A { T a; U b; };"
+    "template<typename T>"
+    "struct A<T, int> { T a; };",
+    classTemplateSpecialization().bind("id"),
+    "struct A {\n}"));
+    // WRONG; Should be: "template<typename T> struct A<T, int> { ... }"
+}
+
+TEST(DeclPrinter, TestClassTemplatePartialSpecializationDecl2) {
+  ASSERT_TRUE(PrintedDeclMatches(
+    "template<typename T>"
+    "struct A { T a; };"
+    "template<typename T>"
+    "struct A<T *> { T a; };",
+    classTemplateSpecialization().bind("id"),
+    "struct A {\n}"));
+    // WRONG; Should be: "template<typename T> struct A<T *> { ... }"
+}
+
+TEST(DeclPrinter, TestClassTemplateSpecializationDecl1) {
+  ASSERT_TRUE(PrintedDeclMatches(
+    "template<typename T>"
+    "struct A { T a; };"
+    "template<>"
+    "struct A<int> { int a; };",
+    classTemplateSpecialization().bind("id"),
+    "struct A {\n}"));
+    // WRONG; Should be: "template<> struct A<int> { ... }"
+}
+
+TEST(DeclPrinter, TestFunctionTemplateDecl1) {
+  ASSERT_TRUE(PrintedDeclMatches(
+    "template<typename T>"
+    "void A(T &t);",
+    functionTemplate(hasName("A")).bind("id"),
+    "template <typename T> void A(T &t)"));
+    // Should be: with semicolon
+}
+
+TEST(DeclPrinter, TestFunctionTemplateDecl2) {
+  ASSERT_TRUE(PrintedDeclMatches(
+    "template<typename T>"
+    "void A(T &t) { }",
+    functionTemplate(hasName("A")).bind("id"),
+    "template <typename T> void A(T &t) {\n}\n\n"));
+    // Should be: without body, with semicolon
+}
+
+TEST(DeclPrinter, TestFunctionTemplateDecl3) {
+  ASSERT_TRUE(PrintedDeclCXX11Matches(
+    "template<typename... T>"
+    "void A(T... a);",
+    functionTemplate(hasName("A")).bind("id"),
+    "template <typename ... T> void A(T a...)"));
+    // WRONG; Should be: "template <typename ... T> void A(T... a)"
+    //        (not "T a...")
+    // Should be: with semicolon.
+}
+
+TEST(DeclPrinter, TestFunctionTemplateDecl4) {
+  ASSERT_TRUE(PrintedDeclMatches(
+    "struct Z { template<typename T> void A(T t); };",
+    functionTemplate(hasName("A")).bind("id"),
+    "template <typename T> void A(T t)"));
+    // Should be: with semicolon
+}
+
+TEST(DeclPrinter, TestFunctionTemplateDecl5) {
+  ASSERT_TRUE(PrintedDeclMatches(
+    "struct Z { template<typename T> void A(T t) {} };",
+    functionTemplate(hasName("A")).bind("id"),
+    "template <typename T> void A(T t) {\n}\n\n"));
+    // Should be: without body, with semicolon
+}
+
+TEST(DeclPrinter, TestFunctionTemplateDecl6) {
+  ASSERT_TRUE(PrintedDeclMatches(
+    "template<typename T >struct Z {"
+    "  template<typename U> void A(U t) {}"
+    "};",
+    functionTemplate(hasName("A")).bind("id"),
+    "template <typename U> void A(U t) {\n}\n\n"));
+    // Should be: without body, with semicolon
+}
+
+TEST(DeclPrinter, TestTemplateArgumentList1) {
+  ASSERT_TRUE(PrintedDeclMatches(
+    "template<typename T> struct Z {};"
+    "struct X {};"
+    "Z<X> A;",
+    "A",
+    "Z<X> A"));
+    // Should be: with semicolon
+}
+
+TEST(DeclPrinter, TestTemplateArgumentList2) {
+  ASSERT_TRUE(PrintedDeclMatches(
+    "template<typename T, typename U> struct Z {};"
+    "struct X {};"
+    "typedef int Y;"
+    "Z<X, Y> A;",
+    "A",
+    "Z<X, Y> A"));
+    // Should be: with semicolon
+}
+
+TEST(DeclPrinter, TestTemplateArgumentList3) {
+  ASSERT_TRUE(PrintedDeclMatches(
+    "template<typename T> struct Z {};"
+    "template<typename T> struct X {};"
+    "Z<X<int> > A;",
+    "A",
+    "Z<X<int> > A"));
+    // Should be: with semicolon
+}
+
+TEST(DeclPrinter, TestTemplateArgumentList4) {
+  ASSERT_TRUE(PrintedDeclCXX11Matches(
+    "template<typename T> struct Z {};"
+    "template<typename T> struct X {};"
+    "Z<X<int>> A;",
+    "A",
+    "Z<X<int> > A"));
+    // Should be: with semicolon, without extra space in "> >"
+}
+
+TEST(DeclPrinter, TestTemplateArgumentList5) {
+  ASSERT_TRUE(PrintedDeclCXX11Matches(
+    "template<typename T> struct Z {};"
+    "template<typename T> struct X { Z<T> A; };",
+    "A",
+    "Z<T> A"));
+    // Should be: with semicolon
+}
+
+TEST(DeclPrinter, TestTemplateArgumentList6) {
+  ASSERT_TRUE(PrintedDeclMatches(
+    "template<template<typename T> class U> struct Z {};"
+    "template<typename T> struct X {};"
+    "Z<X> A;",
+    "A",
+    "Z<X> A"));
+    // Should be: with semicolon
+}
+
+TEST(DeclPrinter, TestTemplateArgumentList7) {
+  ASSERT_TRUE(PrintedDeclCXX11Matches(
+    "template<template<typename T> class U> struct Z {};"
+    "template<template<typename T> class U> struct Y {"
+    "  Z<U> A;"
+    "};",
+    "A",
+    "Z<U> A"));
+    // Should be: with semicolon
+}
+
+TEST(DeclPrinter, TestTemplateArgumentList8) {
+  ASSERT_TRUE(PrintedDeclCXX11Matches(
+    "template<typename T> struct Z {};"
+    "template<template<typename T> class U> struct Y {"
+    "  Z<U<int> > A;"
+    "};",
+    "A",
+    "Z<U<int> > A"));
+    // Should be: with semicolon
+}
+
+TEST(DeclPrinter, TestTemplateArgumentList9) {
+  ASSERT_TRUE(PrintedDeclMatches(
+    "template<unsigned I> struct Z {};"
+    "Z<0> A;",
+    "A",
+    "Z<0> A"));
+    // Should be: with semicolon
+}
+
+TEST(DeclPrinter, TestTemplateArgumentList10) {
+  ASSERT_TRUE(PrintedDeclMatches(
+    "template<unsigned I> struct Z {};"
+    "template<unsigned I> struct X { Z<I> A; };",
+    "A",
+    "Z<I> A"));
+    // Should be: with semicolon
+}
+
+TEST(DeclPrinter, TestTemplateArgumentList11) {
+  ASSERT_TRUE(PrintedDeclMatches(
+    "template<int I> struct Z {};"
+    "Z<42 * 10 - 420 / 1> A;",
+    "A",
+    "Z<42 * 10 - 420 / 1> A"));
+    // Should be: with semicolon
+}
+
+TEST(DeclPrinter, TestTemplateArgumentList12) {
+  ASSERT_TRUE(PrintedDeclMatches(
+    "template<const char *p> struct Z {};"
+    "extern const char X[] = \"aaa\";"
+    "Z<X> A;",
+    "A",
+    "Z<X> A"));
+    // Should be: with semicolon
+}
+
+TEST(DeclPrinter, TestTemplateArgumentList13) {
+  ASSERT_TRUE(PrintedDeclCXX11Matches(
+    "template<typename... T> struct Z {};"
+    "template<typename... T> struct X {"
+    "  Z<T...> A;"
+    "};",
+    "A",
+    "Z<T...> A"));
+    // Should be: with semicolon, without extra space in "> >"
+}
+
+TEST(DeclPrinter, TestTemplateArgumentList14) {
+  ASSERT_TRUE(PrintedDeclCXX11Matches(
+    "template<typename... T> struct Z {};"
+    "template<typename T> struct Y {};"
+    "template<typename... T> struct X {"
+    "  Z<Y<T>...> A;"
+    "};",
+    "A",
+    "Z<Y<T>...> A"));
+    // Should be: with semicolon, without extra space in "> >"
+}
+
+TEST(DeclPrinter, TestTemplateArgumentList15) {
+  ASSERT_TRUE(PrintedDeclCXX11Matches(
+    "template<unsigned I> struct Z {};"
+    "template<typename... T> struct X {"
+    "  Z<sizeof...(T)> A;"
+    "};",
+    "A",
+    "Z<sizeof...(T)> A"));
+    // Should be: with semicolon, without extra space in "> >"
+}
+

Modified: cfe/trunk/unittests/AST/Makefile
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/AST/Makefile?rev=162245&r1=162244&r2=162245&view=diff
==============================================================================
--- cfe/trunk/unittests/AST/Makefile (original)
+++ cfe/trunk/unittests/AST/Makefile Mon Aug 20 18:39:06 2012
@@ -9,7 +9,10 @@
 
 CLANG_LEVEL = ../..
 TESTNAME = AST
-LINK_COMPONENTS := support mc
-USEDLIBS = clangAST.a clangLex.a clangBasic.a
+include $(CLANG_LEVEL)/../../Makefile.config
+LINK_COMPONENTS := $(TARGETS_TO_BUILD) asmparser support mc
+USEDLIBS = clangTooling.a clangFrontend.a clangSerialization.a clangDriver.a \
+           clangRewrite.a clangParse.a clangSema.a clangAnalysis.a \
+           clangAST.a clangASTMatchers.a clangLex.a clangBasic.a clangEdit.a
 
 include $(CLANG_LEVEL)/unittests/Makefile





More information about the cfe-commits mailing list