From 056abd2059c65a3e908193aeae16fad98017437c Mon Sep 17 00:00:00 2001 From: dim Date: Sun, 2 Dec 2012 13:20:44 +0000 Subject: Vendor import of clang release_32 branch r168974 (effectively, 3.2 RC2): http://llvm.org/svn/llvm-project/cfe/branches/release_32@168974 --- unittests/AST/DeclPrinterTest.cpp | 1248 +++++++++++++++++++++++++++++++++++++ 1 file changed, 1248 insertions(+) create mode 100644 unittests/AST/DeclPrinterTest.cpp (limited to 'unittests/AST/DeclPrinterTest.cpp') diff --git a/unittests/AST/DeclPrinterTest.cpp b/unittests/AST/DeclPrinterTest.cpp new file mode 100644 index 0000000..a2fc839 --- /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("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 &Args, + const DeclarationMatcher &NodeMatch, + StringRef ExpectedPrinted, + StringRef FileName) { + PrintMatch Printer; + MatchFinder Finder; + Finder.addMatcher(NodeMatch, &Printer); + OwningPtr 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 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 Args(1, "-std=c++98"); + return PrintedDeclMatches(Code, + Args, + NodeMatch, + ExpectedPrinted, + "input.cc"); +} + +::testing::AssertionResult PrintedDeclCXX11Matches(StringRef Code, + StringRef DeclName, + StringRef ExpectedPrinted) { + std::vector 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 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 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" + "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" + "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" + "struct A : public T... {" + " A(T&&... ts) : T(ts)... {}" + "};", + constructorDecl(ofClass(hasName("A"))).bind("id"), + "A(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" + "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" + "struct Z { T A; };", + "A", + "T A")); + // Should be: with semicolon +} + +TEST(DeclPrinter, TestFieldDecl2) { + ASSERT_TRUE(PrintedDeclCXX98Matches( + "template" + "struct Z { int A[N]; };", + "A", + "int A[N]")); + // Should be: with semicolon +} + +TEST(DeclPrinter, TestClassTemplateDecl1) { + ASSERT_TRUE(PrintedDeclCXX98Matches( + "template" + "struct A { T a; };", + classTemplateDecl(hasName("A")).bind("id"), + "template struct A {\n}")); + // Should be: with semicolon, with { ... } +} + +TEST(DeclPrinter, TestClassTemplateDecl2) { + ASSERT_TRUE(PrintedDeclCXX98Matches( + "template" + "struct A { T a; };", + classTemplateDecl(hasName("A")).bind("id"), + "template struct A {\n}")); + // Should be: with semicolon, with { ... } +} + +TEST(DeclPrinter, TestClassTemplateDecl3) { + ASSERT_TRUE(PrintedDeclCXX98Matches( + "template" + "struct A { T a; };", + classTemplateDecl(hasName("A")).bind("id"), + "template struct A {\n}")); + // Should be: with semicolon, with { ... } +} + +TEST(DeclPrinter, TestClassTemplateDecl4) { + ASSERT_TRUE(PrintedDeclCXX98Matches( + "template" + "struct A { T a; U b; };", + classTemplateDecl(hasName("A")).bind("id"), + "template struct A {\n}")); + // Should be: with semicolon, with { ... } +} + +TEST(DeclPrinter, TestClassTemplateDecl5) { + ASSERT_TRUE(PrintedDeclCXX98Matches( + "template" + "struct A { int a[N]; };", + classTemplateDecl(hasName("A")).bind("id"), + "template struct A {\n}")); + // Should be: with semicolon, with { ... } +} + +TEST(DeclPrinter, TestClassTemplateDecl6) { + ASSERT_TRUE(PrintedDeclCXX98Matches( + "template" + "struct A { int a[N]; };", + classTemplateDecl(hasName("A")).bind("id"), + "template struct A {\n}")); + // Should be: with semicolon, with { ... } +} + +TEST(DeclPrinter, TestClassTemplateDecl7) { + ASSERT_TRUE(PrintedDeclCXX98Matches( + "typedef int MyInt;" + "template" + "struct A { int a[N]; };", + classTemplateDecl(hasName("A")).bind("id"), + "template struct A {\n}")); + // Should be: with semicolon, with { ... } +} + +TEST(DeclPrinter, TestClassTemplateDecl8) { + ASSERT_TRUE(PrintedDeclCXX98Matches( + "template class T> struct A { };", + classTemplateDecl(hasName("A")).bind("id"), + "template