[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

Sean Silva silvas at purdue.edu
Mon Aug 20 19:05:37 PDT 2012


+  /// Don't print contents of DeclContexts.  Used to provide a 'terse' output.
+  unsigned DontRecurseInDeclContext : 1;

Please give a concrete example here of the difference between 'terse'
and non-'terse' output.

--Sean Silva

On Mon, Aug 20, 2012 at 7:39 PM, Dmitri Gribenko <gribozavr at gmail.com> wrote:
> 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
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits



More information about the cfe-commits mailing list