diff options
author | Dmitri Gribenko <gribozavr@gmail.com> | 2012-08-20 23:39:06 +0000 |
---|---|---|
committer | Dmitri Gribenko <gribozavr@gmail.com> | 2012-08-20 23:39:06 +0000 |
commit | 49795ae2c7cbb0845ed07b6626ac24275234e3d1 (patch) | |
tree | a1f19dd5782b617671d058701db6b97ce1780128 /unittests/AST/DeclPrinterTest.cpp | |
parent | d64c2eb83d7ec86faa4f2554935a977a19573f59 (diff) |
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.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@162245 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'unittests/AST/DeclPrinterTest.cpp')
-rw-r--r-- | unittests/AST/DeclPrinterTest.cpp | 1200 |
1 files changed, 1200 insertions, 0 deletions
diff --git a/unittests/AST/DeclPrinterTest.cpp b/unittests/AST/DeclPrinterTest.cpp new file mode 100644 index 0000000000..c86ec2d44a --- /dev/null +++ b/unittests/AST/DeclPrinterTest.cpp @@ -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")); |