diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2012-12-02 13:20:44 +0000 | 
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2012-12-02 13:20:44 +0000 | 
| commit | 13cc256e404620c1de0cbcc4e43ce1e2dbbc4898 (patch) | |
| tree | 2732d02d7d51218d6eed98ac7fcfc5b8794896b5 /unittests/AST/DeclPrinterTest.cpp | |
| parent | 657bc3d9848e3be92029b2416031340988cd0111 (diff) | |
Diffstat (limited to 'unittests/AST/DeclPrinterTest.cpp')
| -rw-r--r-- | unittests/AST/DeclPrinterTest.cpp | 1248 | 
1 files changed, 1248 insertions, 0 deletions
| diff --git a/unittests/AST/DeclPrinterTest.cpp b/unittests/AST/DeclPrinterTest.cpp new file mode 100644 index 000000000000..a2fc839b9c8e --- /dev/null +++ b/unittests/AST/DeclPrinterTest.cpp @@ -0,0 +1,1248 @@ +//===- 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 "llvm/ADT/SmallString.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.TerseOutput = 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; +  } +}; + +::testing::AssertionResult PrintedDeclMatches( +                                  StringRef Code, +                                  const std::vector<std::string> &Args, +                                  const DeclarationMatcher &NodeMatch, +                                  StringRef ExpectedPrinted, +                                  StringRef FileName) { +  PrintMatch Printer; +  MatchFinder Finder; +  Finder.addMatcher(NodeMatch, &Printer); +  OwningPtr<FrontendActionFactory> Factory(newFrontendActionFactory(&Finder)); + +  if (!runToolOnCodeWithArgs(Factory->create(), Code, Args, FileName)) +    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 PrintedDeclCXX98Matches(StringRef Code, +                                                   StringRef DeclName, +                                                   StringRef ExpectedPrinted) { +  std::vector<std::string> Args(1, "-std=c++98"); +  return PrintedDeclMatches(Code, +                            Args, +                            namedDecl(hasName(DeclName)).bind("id"), +                            ExpectedPrinted, +                            "input.cc"); +} + +::testing::AssertionResult PrintedDeclCXX98Matches( +                                  StringRef Code, +                                  const DeclarationMatcher &NodeMatch, +                                  StringRef ExpectedPrinted) { +  std::vector<std::string> Args(1, "-std=c++98"); +  return PrintedDeclMatches(Code, +                            Args, +                            NodeMatch, +                            ExpectedPrinted, +                            "input.cc"); +} + +::testing::AssertionResult PrintedDeclCXX11Matches(StringRef Code, +                                                   StringRef DeclName, +                                                   StringRef ExpectedPrinted) { +  std::vector<std::string> Args(1, "-std=c++11"); +  return PrintedDeclMatches(Code, +                            Args, +                            namedDecl(hasName(DeclName)).bind("id"), +                            ExpectedPrinted, +                            "input.cc"); +} + +::testing::AssertionResult PrintedDeclCXX11Matches( +                                  StringRef Code, +                                  const DeclarationMatcher &NodeMatch, +                                  StringRef ExpectedPrinted) { +  std::vector<std::string> Args(1, "-std=c++11"); +  return PrintedDeclMatches(Code, +                            Args, +                            NodeMatch, +                            ExpectedPrinted, +                            "input.cc"); +} + +::testing::AssertionResult PrintedDeclObjCMatches( +                                  StringRef Code, +                                  const DeclarationMatcher &NodeMatch, +                                  StringRef ExpectedPrinted) { +  std::vector<std::string> Args(1, ""); +  return PrintedDeclMatches(Code, +                            Args, +                            NodeMatch, +                            ExpectedPrinted, +                            "input.m"); +} + +} // unnamed namespace + +TEST(DeclPrinter, TestNamespace1) { +  ASSERT_TRUE(PrintedDeclCXX98Matches( +    "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(PrintedDeclCXX98Matches( +    "namespace Z { }" +    "namespace A = Z;", +    "A", +    "namespace A = Z")); +    // Should be: with semicolon +} + +TEST(DeclPrinter, TestNamespaceAlias2) { +  ASSERT_TRUE(PrintedDeclCXX98Matches( +    "namespace X { namespace Y {} }" +    "namespace A = X::Y;", +    "A", +    "namespace A = X::Y")); +    // Should be: with semicolon +} + +TEST(DeclPrinter, TestCXXRecordDecl1) { +  ASSERT_TRUE(PrintedDeclCXX98Matches( +    "class A { int a; };", +    "A", +    "class A {\n}")); +    // Should be: with semicolon, with { ... } +} + +TEST(DeclPrinter, TestCXXRecordDecl2) { +  ASSERT_TRUE(PrintedDeclCXX98Matches( +    "struct A { int a; };", +    "A", +    "struct A {\n}")); +    // Should be: with semicolon, with { ... } +} + +TEST(DeclPrinter, TestCXXRecordDecl3) { +  ASSERT_TRUE(PrintedDeclCXX98Matches( +    "union A { int a; };", +    "A", +    "union A {\n}")); +    // Should be: with semicolon, with { ... } +} + +TEST(DeclPrinter, TestCXXRecordDecl4) { +  ASSERT_TRUE(PrintedDeclCXX98Matches( +    "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(PrintedDeclCXX98Matches( +    "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(PrintedDeclCXX98Matches( +    "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(PrintedDeclCXX98Matches( +    "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(PrintedDeclCXX98Matches( +    "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(PrintedDeclCXX98Matches( +    "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(PrintedDeclCXX98Matches( +    "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(PrintedDeclCXX98Matches( +    "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(PrintedDeclCXX98Matches( +    "void A();", +    "A", +    "void A()")); +    // Should be: with semicolon +} + +TEST(DeclPrinter, TestFunctionDecl2) { +  ASSERT_TRUE(PrintedDeclCXX98Matches( +    "void A() {}", +    "A", +    "void A()")); +    // Should be: with semicolon +} + +TEST(DeclPrinter, TestFunctionDecl3) { +  ASSERT_TRUE(PrintedDeclCXX98Matches( +    "void Z();" +    "void A() { Z(); }", +    "A", +    "void A()")); +    // Should be: with semicolon +} + +TEST(DeclPrinter, TestFunctionDecl4) { +  ASSERT_TRUE(PrintedDeclCXX98Matches( +    "extern void A();", +    "A", +    "extern void A()")); +    // Should be: with semicolon +} + +TEST(DeclPrinter, TestFunctionDecl5) { +  ASSERT_TRUE(PrintedDeclCXX98Matches( +    "static void A();", +    "A", +    "static void A()")); +    // Should be: with semicolon +} + +TEST(DeclPrinter, TestFunctionDecl6) { +  ASSERT_TRUE(PrintedDeclCXX98Matches( +    "inline void A();", +    "A", +    "inline void A()")); +    // Should be: with semicolon +} + +TEST(DeclPrinter, TestFunctionDecl7) { +  ASSERT_TRUE(PrintedDeclCXX11Matches( +    "constexpr int A(int a);", +    "A", +    "int A(int a)")); +    // WRONG; Should be: "constexpr int A(int a);" +} + +TEST(DeclPrinter, TestFunctionDecl8) { +  ASSERT_TRUE(PrintedDeclCXX98Matches( +    "void A(int a);", +    "A", +    "void A(int a)")); +    // Should be: with semicolon +} + +TEST(DeclPrinter, TestFunctionDecl9) { +  ASSERT_TRUE(PrintedDeclCXX98Matches( +    "void A(...);", +    "A", +    "void A(...)")); +    // Should be: with semicolon +} + +TEST(DeclPrinter, TestFunctionDecl10) { +  ASSERT_TRUE(PrintedDeclCXX98Matches( +    "void A(int a, ...);", +    "A", +    "void A(int a, ...)")); +    // Should be: with semicolon +} + +TEST(DeclPrinter, TestFunctionDecl11) { +  ASSERT_TRUE(PrintedDeclCXX98Matches( +    "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, TestFunctionDecl12) { +  ASSERT_TRUE(PrintedDeclCXX98Matches( +    "void A(int a, int b = 0);", +    "A", +    "void A(int a, int b = 0)")); +    // Should be: with semicolon +} + +TEST(DeclPrinter, TestFunctionDecl13) { +  ASSERT_TRUE(PrintedDeclCXX98Matches( +    "void (*A(int a))(int b);", +    "A", +    "void (*A(int a))(int)")); +    // Should be: with semicolon, with parameter name (?) +} + +TEST(DeclPrinter, TestFunctionDecl14) { +  ASSERT_TRUE(PrintedDeclCXX98Matches( +    "template<typename T>" +    "void A(T t) { }" +    "template<>" +    "void A(int N) { }", +    functionDecl(hasName("A"), isExplicitTemplateSpecialization()).bind("id"), +    "void A(int N)")); +    // WRONG; Should be: "template <> void A(int N);")); +} + + +TEST(DeclPrinter, TestCXXConstructorDecl1) { +  ASSERT_TRUE(PrintedDeclCXX98Matches( +    "struct A {" +    "  A();" +    "};", +    constructorDecl(ofClass(hasName("A"))).bind("id"), +    "")); +    // WRONG; Should be: "A();" +} + +TEST(DeclPrinter, TestCXXConstructorDecl2) { +  ASSERT_TRUE(PrintedDeclCXX98Matches( +    "struct A {" +    "  A(int a);" +    "};", +    constructorDecl(ofClass(hasName("A"))).bind("id"), +    "")); +    // WRONG; Should be: "A(int a);" +} + +TEST(DeclPrinter, TestCXXConstructorDecl3) { +  ASSERT_TRUE(PrintedDeclCXX98Matches( +    "struct A {" +    "  A(const A &a);" +    "};", +    constructorDecl(ofClass(hasName("A"))).bind("id"), +    "")); +    // WRONG; Should be: "A(const A &a);" +} + +TEST(DeclPrinter, TestCXXConstructorDecl4) { +  ASSERT_TRUE(PrintedDeclCXX98Matches( +    "struct A {" +    "  A(const A &a, int = 0);" +    "};", +    constructorDecl(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);" +    "};", +    constructorDecl(ofClass(hasName("A"))).bind("id"), +    "")); +    // WRONG; Should be: "A(const A &&a);" +} + +TEST(DeclPrinter, TestCXXConstructorDecl6) { +  ASSERT_TRUE(PrintedDeclCXX98Matches( +    "struct A {" +    "  explicit A(int a);" +    "};", +    constructorDecl(ofClass(hasName("A"))).bind("id"), +    "")); +    // WRONG; Should be: "explicit A(int a);" +} + +TEST(DeclPrinter, TestCXXConstructorDecl7) { +  ASSERT_TRUE(PrintedDeclCXX11Matches( +    "struct A {" +    "  constexpr A();" +    "};", +    constructorDecl(ofClass(hasName("A"))).bind("id"), +    "")); +    // WRONG; Should be: "constexpr A();" +} + +TEST(DeclPrinter, TestCXXConstructorDecl8) { +  ASSERT_TRUE(PrintedDeclCXX11Matches( +    "struct A {" +    "  A() = default;" +    "};", +    constructorDecl(ofClass(hasName("A"))).bind("id"), +    "")); +    // WRONG; Should be: "A() = default;" +} + +TEST(DeclPrinter, TestCXXConstructorDecl9) { +  ASSERT_TRUE(PrintedDeclCXX11Matches( +    "struct A {" +    "  A() = delete;" +    "};", +    constructorDecl(ofClass(hasName("A"))).bind("id"), +    " = delete")); +    // WRONG; Should be: "A() = delete;" +} + +TEST(DeclPrinter, TestCXXConstructorDecl10) { +  ASSERT_TRUE(PrintedDeclCXX11Matches( +    "template<typename... T>" +    "struct A {" +    "  A(const A &a);" +    "};", +    constructorDecl(ofClass(hasName("A"))).bind("id"), +    "")); +    // WRONG; Should be: "A(const A &a);" +} + +#if !defined(_MSC_VER) +TEST(DeclPrinter, TestCXXConstructorDecl11) { +  ASSERT_TRUE(PrintedDeclCXX11Matches( +    "template<typename... T>" +    "struct A : public T... {" +    "  A(T&&... ts) : T(ts)... {}" +    "};", +    constructorDecl(ofClass(hasName("A"))).bind("id"), +    "A<T...>(T &&ts...) : T(ts)")); +    // WRONG; Should be: "A(T&&... ts) : T(ts)..." +} +#endif + +TEST(DeclPrinter, TestCXXDestructorDecl1) { +  ASSERT_TRUE(PrintedDeclCXX98Matches( +    "struct A {" +    "  ~A();" +    "};", +    destructorDecl(ofClass(hasName("A"))).bind("id"), +    "void ~A()")); +    // WRONG; Should be: "~A();" +} + +TEST(DeclPrinter, TestCXXDestructorDecl2) { +  ASSERT_TRUE(PrintedDeclCXX98Matches( +    "struct A {" +    "  virtual ~A();" +    "};", +    destructorDecl(ofClass(hasName("A"))).bind("id"), +    "virtual void ~A()")); +    // WRONG; Should be: "virtual ~A();" +} + +TEST(DeclPrinter, TestCXXConversionDecl1) { +  ASSERT_TRUE(PrintedDeclCXX98Matches( +    "struct A {" +    "  operator int();" +    "};", +    methodDecl(ofClass(hasName("A"))).bind("id"), +    "int operator int()")); +    // WRONG; Should be: "operator int();" +} + +TEST(DeclPrinter, TestCXXConversionDecl2) { +  ASSERT_TRUE(PrintedDeclCXX98Matches( +    "struct A {" +    "  operator bool();" +    "};", +    methodDecl(ofClass(hasName("A"))).bind("id"), +    "bool operator _Bool()")); +    // WRONG; Should be: "operator bool();" +} + +TEST(DeclPrinter, TestCXXConversionDecl3) { +  ASSERT_TRUE(PrintedDeclCXX98Matches( +    "struct Z {};" +    "struct A {" +    "  operator Z();" +    "};", +    methodDecl(ofClass(hasName("A"))).bind("id"), +    "Z operator struct Z()")); +    // WRONG; Should be: "operator Z();" +} + +TEST(DeclPrinter, TestCXXMethodDecl_AllocationFunction1) { +  ASSERT_TRUE(PrintedDeclCXX11Matches( +    "namespace std { typedef decltype(sizeof(int)) size_t; }" +    "struct Z {" +    "  void *operator new(std::size_t);" +    "};", +    methodDecl(ofClass(hasName("Z"))).bind("id"), +    "void *operator new(std::size_t)")); +    // Should be: with semicolon +} + +TEST(DeclPrinter, TestCXXMethodDecl_AllocationFunction2) { +  ASSERT_TRUE(PrintedDeclCXX11Matches( +    "namespace std { typedef decltype(sizeof(int)) size_t; }" +    "struct Z {" +    "  void *operator new[](std::size_t);" +    "};", +    methodDecl(ofClass(hasName("Z"))).bind("id"), +    "void *operator new[](std::size_t)")); +    // Should be: with semicolon +} + +TEST(DeclPrinter, TestCXXMethodDecl_AllocationFunction3) { +  ASSERT_TRUE(PrintedDeclCXX11Matches( +    "struct Z {" +    "  void operator delete(void *);" +    "};", +    methodDecl(ofClass(hasName("Z"))).bind("id"), +    "void operator delete(void *) noexcept")); +    // Should be: with semicolon, without noexcept? +} + +TEST(DeclPrinter, TestCXXMethodDecl_AllocationFunction4) { +  ASSERT_TRUE(PrintedDeclCXX98Matches( +    "struct Z {" +    "  void operator delete(void *);" +    "};", +    methodDecl(ofClass(hasName("Z"))).bind("id"), +    "void operator delete(void *)")); +    // Should be: with semicolon +} + +TEST(DeclPrinter, TestCXXMethodDecl_AllocationFunction5) { +  ASSERT_TRUE(PrintedDeclCXX11Matches( +    "struct Z {" +    "  void operator delete[](void *);" +    "};", +    methodDecl(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(PrintedDeclCXX98Matches( +      Code, +      methodDecl(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(PrintedDeclCXX98Matches( +      Code, +      methodDecl(ofClass(hasName("Z"))).bind("id"), +      Expected)); +  } +} + +TEST(DeclPrinter, TestCXXMethodDecl1) { +  ASSERT_TRUE(PrintedDeclCXX98Matches( +    "struct Z {" +    "  void A(int a);" +    "};", +    "A", +    "void A(int a)")); +    // Should be: with semicolon +} + +TEST(DeclPrinter, TestCXXMethodDecl2) { +  ASSERT_TRUE(PrintedDeclCXX98Matches( +    "struct Z {" +    "  virtual void A(int a);" +    "};", +    "A", +    "virtual void A(int a)")); +    // Should be: with semicolon +} + +TEST(DeclPrinter, TestCXXMethodDecl3) { +  ASSERT_TRUE(PrintedDeclCXX98Matches( +    "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(PrintedDeclCXX98Matches( +    "struct Z {" +    "  inline void A(int a);" +    "};", +    "A", +    "inline void A(int a)")); +    // Should be: with semicolon +} + +TEST(DeclPrinter, TestCXXMethodDecl5) { +  ASSERT_TRUE(PrintedDeclCXX98Matches( +    "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(PrintedDeclCXX98Matches( +    "struct Z {" +    "  void A(int a) const;" +    "};", +    "A", +    "void A(int a) const")); +    // Should be: with semicolon +} + +TEST(DeclPrinter, TestCXXMethodDecl_CVQualifier2) { +  ASSERT_TRUE(PrintedDeclCXX98Matches( +    "struct Z {" +    "  void A(int a) volatile;" +    "};", +    "A", +    "void A(int a) volatile")); +    // Should be: with semicolon +} + +TEST(DeclPrinter, TestCXXMethodDecl_CVQualifier3) { +  ASSERT_TRUE(PrintedDeclCXX98Matches( +    "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(PrintedDeclCXX98Matches( +    "struct Z {" +    "  void A(int a) throw();" +    "};", +    "A", +    "void A(int a) throw()")); +    // Should be: with semicolon +} + +TEST(DeclPrinter, TestFunctionDecl_ExceptionSpecification2) { +  ASSERT_TRUE(PrintedDeclCXX98Matches( +    "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(PrintedDeclCXX98Matches( +    "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(PrintedDeclCXX98Matches( +    "char *const (*(*A)[5])(int);", +    "A", +    "char *const (*(*A)[5])(int)")); +    // Should be: with semicolon +} + +TEST(DeclPrinter, TestVarDecl2) { +  ASSERT_TRUE(PrintedDeclCXX98Matches( +    "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(PrintedDeclCXX98Matches( +    "template<typename T>" +    "struct Z { T A; };", +    "A", +    "T A")); +    // Should be: with semicolon +} + +TEST(DeclPrinter, TestFieldDecl2) { +  ASSERT_TRUE(PrintedDeclCXX98Matches( +    "template<int N>" +    "struct Z { int A[N]; };", +    "A", +    "int A[N]")); +    // Should be: with semicolon +} + +TEST(DeclPrinter, TestClassTemplateDecl1) { +  ASSERT_TRUE(PrintedDeclCXX98Matches( +    "template<typename T>" +    "struct A { T a; };", +    classTemplateDecl(hasName("A")).bind("id"), +    "template <typename T> struct A {\n}")); +    // Should be: with semicolon, with { ... } +} + +TEST(DeclPrinter, TestClassTemplateDecl2) { +  ASSERT_TRUE(PrintedDeclCXX98Matches( +    "template<typename T = int>" +    "struct A { T a; };", +    classTemplateDecl(hasName("A")).bind("id"), +    "template <typename T = int> struct A {\n}")); +    // Should be: with semicolon, with { ... } +} + +TEST(DeclPrinter, TestClassTemplateDecl3) { +  ASSERT_TRUE(PrintedDeclCXX98Matches( +    "template<class T>" +    "struct A { T a; };", +    classTemplateDecl(hasName("A")).bind("id"), +    "template <class T> struct A {\n}")); +    // Should be: with semicolon, with { ... } +} + +TEST(DeclPrinter, TestClassTemplateDecl4) { +  ASSERT_TRUE(PrintedDeclCXX98Matches( +    "template<typename T, typename U>" +    "struct A { T a; U b; };", +    classTemplateDecl(hasName("A")).bind("id"), +    "template <typename T, typename U> struct A {\n}")); +    // Should be: with semicolon, with { ... } +} + +TEST(DeclPrinter, TestClassTemplateDecl5) { +  ASSERT_TRUE(PrintedDeclCXX98Matches( +    "template<int N>" +    "struct A { int a[N]; };", +    classTemplateDecl(hasName("A")).bind("id"), +    "template <int N> struct A {\n}")); +    // Should be: with semicolon, with { ... } +} + +TEST(DeclPrinter, TestClassTemplateDecl6) { +  ASSERT_TRUE(PrintedDeclCXX98Matches( +    "template<int N = 42>" +    "struct A { int a[N]; };", +    classTemplateDecl(hasName("A")).bind("id"), +    "template <int N = 42> struct A {\n}")); +    // Should be: with semicolon, with { ... } +} + +TEST(DeclPrinter, TestClassTemplateDecl7) { +  ASSERT_TRUE(PrintedDeclCXX98Matches( +    "typedef int MyInt;" +    "template<MyInt N>" +    "struct A { int a[N]; };", +    classTemplateDecl(hasName("A")).bind("id"), +    "template <MyInt N> struct A {\n}")); +    // Should be: with semicolon, with { ... } +} + +TEST(DeclPrinter, TestClassTemplateDecl8) { +  ASSERT_TRUE(PrintedDeclCXX98Matches( +    "template<template<typename U> class T> struct A { };", +    classTemplateDecl(hasName("A")).bind("id"), +    "template <template <typename U> class T> struct A {\n}")); +    // Should be: with semicolon, with { ... } +} + +TEST(DeclPrinter, TestClassTemplateDecl9) { +  ASSERT_TRUE(PrintedDeclCXX98Matches( +    "template<typename T> struct Z { };" +    "template<template<typename U> class T = Z> struct A { };", +    classTemplateDecl(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; };", +    classTemplateDecl(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; };", +    classTemplateDecl(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(PrintedDeclCXX98Matches( +    "template<typename T, typename U>" +    "struct A { T a; U b; };" +    "template<typename T>" +    "struct A<T, int> { T a; };", +    classTemplateSpecializationDecl().bind("id"), +    "struct A {\n}")); +    // WRONG; Should be: "template<typename T> struct A<T, int> { ... }" +} + +TEST(DeclPrinter, TestClassTemplatePartialSpecializationDecl2) { +  ASSERT_TRUE(PrintedDeclCXX98Matches( +    "template<typename T>" +    "struct A { T a; };" +    "template<typename T>" +    "struct A<T *> { T a; };", +    classTemplateSpecializationDecl().bind("id"), +    "struct A {\n}")); +    // WRONG; Should be: "template<typename T> struct A<T *> { ... }" +} + +TEST(DeclPrinter, TestClassTemplateSpecializationDecl1) { +  ASSERT_TRUE(PrintedDeclCXX98Matches( +    "template<typename T>" +    "struct A { T a; };" +    "template<>" +    "struct A<int> { int a; };", +    classTemplateSpecializationDecl().bind("id"), +    "struct A {\n}")); +    // WRONG; Should be: "template<> struct A<int> { ... }" +} + +TEST(DeclPrinter, TestFunctionTemplateDecl1) { +  ASSERT_TRUE(PrintedDeclCXX98Matches( +    "template<typename T>" +    "void A(T &t);", +    functionTemplateDecl(hasName("A")).bind("id"), +    "template <typename T> void A(T &t)")); +    // Should be: with semicolon +} + +TEST(DeclPrinter, TestFunctionTemplateDecl2) { +  ASSERT_TRUE(PrintedDeclCXX98Matches( +    "template<typename T>" +    "void A(T &t) { }", +    functionTemplateDecl(hasName("A")).bind("id"), +    "template <typename T> void A(T &t)")); +    // Should be: with semicolon +} + +TEST(DeclPrinter, TestFunctionTemplateDecl3) { +  ASSERT_TRUE(PrintedDeclCXX11Matches( +    "template<typename... T>" +    "void A(T... a);", +    functionTemplateDecl(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(PrintedDeclCXX98Matches( +    "struct Z { template<typename T> void A(T t); };", +    functionTemplateDecl(hasName("A")).bind("id"), +    "template <typename T> void A(T t)")); +    // Should be: with semicolon +} + +TEST(DeclPrinter, TestFunctionTemplateDecl5) { +  ASSERT_TRUE(PrintedDeclCXX98Matches( +    "struct Z { template<typename T> void A(T t) {} };", +    functionTemplateDecl(hasName("A")).bind("id"), +    "template <typename T> void A(T t)")); +    // Should be: with semicolon +} + +TEST(DeclPrinter, TestFunctionTemplateDecl6) { +  ASSERT_TRUE(PrintedDeclCXX98Matches( +    "template<typename T >struct Z {" +    "  template<typename U> void A(U t) {}" +    "};", +    functionTemplateDecl(hasName("A")).bind("id"), +    "template <typename U> void A(U t)")); +    // Should be: with semicolon +} + +TEST(DeclPrinter, TestTemplateArgumentList1) { +  ASSERT_TRUE(PrintedDeclCXX98Matches( +    "template<typename T> struct Z {};" +    "struct X {};" +    "Z<X> A;", +    "A", +    "Z<X> A")); +    // Should be: with semicolon +} + +TEST(DeclPrinter, TestTemplateArgumentList2) { +  ASSERT_TRUE(PrintedDeclCXX98Matches( +    "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(PrintedDeclCXX98Matches( +    "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(PrintedDeclCXX98Matches( +    "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(PrintedDeclCXX98Matches( +    "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(PrintedDeclCXX98Matches( +    "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(PrintedDeclCXX98Matches( +    "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(PrintedDeclCXX98Matches( +    "template<unsigned I> struct Z {};" +    "Z<0> A;", +    "A", +    "Z<0> A")); +    // Should be: with semicolon +} + +TEST(DeclPrinter, TestTemplateArgumentList10) { +  ASSERT_TRUE(PrintedDeclCXX98Matches( +    "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(PrintedDeclCXX98Matches( +    "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(PrintedDeclCXX98Matches( +    "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 "> >" +} + +TEST(DeclPrinter, TestObjCMethod1) { +  ASSERT_TRUE(PrintedDeclObjCMatches( +    "__attribute__((objc_root_class)) @interface X\n" +    "- (int)A:(id)anObject inRange:(long)range;\n" +    "@end\n" +    "@implementation X\n" +    "- (int)A:(id)anObject inRange:(long)range { int printThis; return 0; }\n" +    "@end\n", +    namedDecl(hasName("A:inRange:"), +              hasDescendant(namedDecl(hasName("printThis")))).bind("id"), +    "- (int) A:(id)anObject inRange:(long)range")); +} + | 
