[cfe-commits] r162245 - in /cfe/trunk: include/clang/AST/PrettyPrinter.h lib/AST/DeclPrinter.cpp unittests/AST/CMakeLists.txt unittests/AST/DeclPrinterTest.cpp unittests/AST/Makefile
Dmitri Gribenko
gribozavr at gmail.com
Mon Aug 20 16:39:06 PDT 2012
Author: gribozavr
Date: Mon Aug 20 18:39:06 2012
New Revision: 162245
URL: http://llvm.org/viewvc/llvm-project?rev=162245&view=rev
Log:
DeclPrinter: add terse output mode and lots of tests
Add a flag PrintingPolicy::DontRecurseInDeclContext to provide "terse" output
from DeclPrinter. The motivation is to use DeclPrinter to print declarations
in user-friendly format, without overwhelming user with inner detail of the
declaration being printed.
Also add many tests for DeclPrinter. There are quite a few things that we
print incorrectly: search for WRONG in DeclPrinterTest.cpp -- and these tests
check our output against incorrect output, so that we can fix/refactor/rewrite
the DeclPrinter later.
Added:
cfe/trunk/unittests/AST/DeclPrinterTest.cpp
Modified:
cfe/trunk/include/clang/AST/PrettyPrinter.h
cfe/trunk/lib/AST/DeclPrinter.cpp
cfe/trunk/unittests/AST/CMakeLists.txt
cfe/trunk/unittests/AST/Makefile
Modified: cfe/trunk/include/clang/AST/PrettyPrinter.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/PrettyPrinter.h?rev=162245&r1=162244&r2=162245&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/PrettyPrinter.h (original)
+++ cfe/trunk/include/clang/AST/PrettyPrinter.h Mon Aug 20 18:39:06 2012
@@ -39,7 +39,7 @@
SuppressUnwrittenScope(false), SuppressInitializers(false),
ConstantArraySizeAsWritten(false), AnonymousTagLocations(true),
SuppressStrongLifetime(false), Bool(LO.Bool),
- DumpSourceManager(0) { }
+ DontRecurseInDeclContext(false), DumpSourceManager(0) { }
/// \brief What language we're printing.
LangOptions LangOpts;
@@ -134,6 +134,9 @@
/// doesn't actually have 'bool' (because, e.g., it is defined as a macro).
unsigned Bool : 1;
+ /// Don't print contents of DeclContexts. Used to provide a 'terse' output.
+ unsigned DontRecurseInDeclContext : 1;
+
/// \brief If we are "dumping" rather than "pretty-printing", this points to
/// a SourceManager which will be used to dump SourceLocations. Dumping
/// involves printing the internal details of the AST and pretty-printing
Modified: cfe/trunk/lib/AST/DeclPrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclPrinter.cpp?rev=162245&r1=162244&r2=162245&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclPrinter.cpp (original)
+++ cfe/trunk/lib/AST/DeclPrinter.cpp Mon Aug 20 18:39:06 2012
@@ -220,6 +220,9 @@
//----------------------------------------------------------------------------
void DeclPrinter::VisitDeclContext(DeclContext *DC, bool Indent) {
+ if (Policy.DontRecurseInDeclContext)
+ return;
+
if (Indent)
Indentation += Policy.Indentation;
Modified: cfe/trunk/unittests/AST/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/AST/CMakeLists.txt?rev=162245&r1=162244&r2=162245&view=diff
==============================================================================
--- cfe/trunk/unittests/AST/CMakeLists.txt (original)
+++ cfe/trunk/unittests/AST/CMakeLists.txt Mon Aug 20 18:39:06 2012
@@ -1,8 +1,9 @@
add_clang_unittest(ASTTests
CommentLexer.cpp
CommentParser.cpp
+ DeclPrinterTest.cpp
)
target_link_libraries(ASTTests
- clangAST
+ clangAST clangASTMatchers clangTooling
)
Added: cfe/trunk/unittests/AST/DeclPrinterTest.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/AST/DeclPrinterTest.cpp?rev=162245&view=auto
==============================================================================
--- cfe/trunk/unittests/AST/DeclPrinterTest.cpp (added)
+++ cfe/trunk/unittests/AST/DeclPrinterTest.cpp Mon Aug 20 18:39:06 2012
@@ -0,0 +1,1200 @@
+//===- unittests/AST/DeclPrinterTest.cpp --- Declaration printer tests ----===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains tests for Decl::print() and related methods.
+//
+// Search this file for WRONG to see test cases that are producing something
+// completely wrong, invalid C++ or just misleading.
+//
+// These tests have a coding convention:
+// * declaration to be printed is named 'A' unless it should have some special
+// name (e.g., 'operator+');
+// * additional helper declarations are 'Z', 'Y', 'X' and so on.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Tooling/Tooling.h"
+#include "gtest/gtest.h"
+
+using namespace clang;
+using namespace ast_matchers;
+using namespace tooling;
+
+namespace {
+
+void PrintDecl(raw_ostream &Out, const ASTContext *Context, const Decl *D) {
+ PrintingPolicy Policy = Context->getPrintingPolicy();
+ Policy.DontRecurseInDeclContext = true;
+ D->print(Out, Policy, /*Indentation*/ 0, /*PrintInstantiation*/ false);
+}
+
+class PrintMatch : public MatchFinder::MatchCallback {
+ SmallString<1024> Printed;
+ unsigned NumFoundDecls;
+
+public:
+ PrintMatch() : NumFoundDecls(0) {}
+
+ virtual void run(const MatchFinder::MatchResult &Result) {
+ const Decl *D = Result.Nodes.getDeclAs<Decl>("id");
+ if (!D || D->isImplicit())
+ return;
+ NumFoundDecls++;
+ if (NumFoundDecls > 1)
+ return;
+
+ llvm::raw_svector_ostream Out(Printed);
+ PrintDecl(Out, Result.Context, D);
+ }
+
+ StringRef getPrinted() const {
+ return Printed;
+ }
+
+ unsigned getNumFoundDecls() const {
+ return NumFoundDecls;
+ }
+};
+
+bool runToolOnCode(clang::FrontendAction *ToolAction, const Twine &Code,
+ ArrayRef<const char *> ClangArgs) {
+ SmallString<16> FileNameStorage;
+ StringRef FileNameRef = "input.cc";
+
+ std::vector<std::string> ArgVector;
+ ArgVector.push_back("clang-tool");
+ ArgVector.push_back("-fsyntax-only");
+ ArgVector.push_back(FileNameRef.data());
+ for (unsigned i = 0, e = ClangArgs.size(); i != e; ++i)
+ ArgVector.push_back(ClangArgs[i]);
+
+ FileManager Files((FileSystemOptions()));
+ ToolInvocation Invocation(ArgVector, ToolAction, &Files);
+
+ SmallString<1024> CodeStorage;
+ Invocation.mapVirtualFile(FileNameRef,
+ Code.toNullTerminatedStringRef(CodeStorage));
+ return Invocation.run();
+}
+
+::testing::AssertionResult PrintedDeclMatches(
+ StringRef Code,
+ ArrayRef<const char *> ClangArgs,
+ const DeclarationMatcher &NodeMatch,
+ StringRef ExpectedPrinted) {
+ PrintMatch Printer;
+ MatchFinder Finder;
+ Finder.addMatcher(NodeMatch, &Printer);
+ OwningPtr<FrontendActionFactory> Factory(newFrontendActionFactory(&Finder));
+
+ if (!runToolOnCode(Factory->create(), Code, ClangArgs))
+ return testing::AssertionFailure() << "Parsing error in \"" << Code << "\"";
+
+ if (Printer.getNumFoundDecls() == 0)
+ return testing::AssertionFailure()
+ << "Matcher didn't find any declarations";
+
+ if (Printer.getNumFoundDecls() > 1)
+ return testing::AssertionFailure()
+ << "Matcher should match only one declaration "
+ "(found " << Printer.getNumFoundDecls() << ")";
+
+ if (Printer.getPrinted() != ExpectedPrinted)
+ return ::testing::AssertionFailure()
+ << "Expected \"" << ExpectedPrinted << "\", "
+ "got \"" << Printer.getPrinted() << "\"";
+
+ return ::testing::AssertionSuccess();
+}
+
+::testing::AssertionResult PrintedDeclMatches(StringRef Code,
+ StringRef DeclName,
+ StringRef ExpectedPrinted) {
+ return PrintedDeclMatches(Code,
+ ArrayRef<const char *>(),
+ nameableDeclaration(hasName(DeclName)).bind("id"),
+ ExpectedPrinted);
+}
+
+::testing::AssertionResult PrintedDeclMatches(
+ StringRef Code,
+ const DeclarationMatcher &NodeMatch,
+ StringRef ExpectedPrinted) {
+ return PrintedDeclMatches(Code,
+ ArrayRef<const char *>(),
+ NodeMatch,
+ ExpectedPrinted);
+}
+
+::testing::AssertionResult PrintedDeclCXX11Matches(StringRef Code,
+ StringRef DeclName,
+ StringRef ExpectedPrinted) {
+ return PrintedDeclMatches(Code,
+ ArrayRef<const char *>("-std=c++11"),
+ nameableDeclaration(hasName(DeclName)).bind("id"),
+ ExpectedPrinted);
+}
+
+::testing::AssertionResult PrintedDeclCXX11Matches(
+ StringRef Code,
+ const DeclarationMatcher &NodeMatch,
+ StringRef ExpectedPrinted) {
+ return PrintedDeclMatches(Code,
+ ArrayRef<const char *>("-std=c++11"),
+ NodeMatch,
+ ExpectedPrinted);
+}
+
+} // unnamed namespace
+
+TEST(DeclPrinter, TestNamespace1) {
+ ASSERT_TRUE(PrintedDeclMatches(
+ "namespace A { int B; }",
+ "A",
+ "namespace A {\n}"));
+ // Should be: with { ... }
+}
+
+TEST(DeclPrinter, TestNamespace2) {
+ ASSERT_TRUE(PrintedDeclCXX11Matches(
+ "inline namespace A { int B; }",
+ "A",
+ "inline namespace A {\n}"));
+ // Should be: with { ... }
+}
+
+TEST(DeclPrinter, TestNamespaceAlias1) {
+ ASSERT_TRUE(PrintedDeclMatches(
+ "namespace Z { }"
+ "namespace A = Z;",
+ "A",
+ "namespace A = Z"));
+ // Should be: with semicolon
+}
+
+TEST(DeclPrinter, TestNamespaceAlias2) {
+ ASSERT_TRUE(PrintedDeclMatches(
+ "namespace X { namespace Y {} }"
+ "namespace A = X::Y;",
+ "A",
+ "namespace A = X::Y"));
+ // Should be: with semicolon
+}
+
+TEST(DeclPrinter, TestCXXRecordDecl1) {
+ ASSERT_TRUE(PrintedDeclMatches(
+ "class A { int a; };",
+ "A",
+ "class A {\n}"));
+ // Should be: with semicolon, with { ... }
+}
+
+TEST(DeclPrinter, TestCXXRecordDecl2) {
+ ASSERT_TRUE(PrintedDeclMatches(
+ "struct A { int a; };",
+ "A",
+ "struct A {\n}"));
+ // Should be: with semicolon, with { ... }
+}
+
+TEST(DeclPrinter, TestCXXRecordDecl3) {
+ ASSERT_TRUE(PrintedDeclMatches(
+ "union A { int a; };",
+ "A",
+ "union A {\n}"));
+ // Should be: with semicolon, with { ... }
+}
+
+TEST(DeclPrinter, TestCXXRecordDecl4) {
+ ASSERT_TRUE(PrintedDeclMatches(
+ "class Z { int a; };"
+ "class A : Z { int b; };",
+ "A",
+ "class A : Z {\n}"));
+ // Should be: with semicolon, with { ... }, without two spaces
+}
+
+TEST(DeclPrinter, TestCXXRecordDecl5) {
+ ASSERT_TRUE(PrintedDeclMatches(
+ "struct Z { int a; };"
+ "struct A : Z { int b; };",
+ "A",
+ "struct A : Z {\n}"));
+ // Should be: with semicolon, with { ... }, without two spaces
+}
+
+TEST(DeclPrinter, TestCXXRecordDecl6) {
+ ASSERT_TRUE(PrintedDeclMatches(
+ "class Z { int a; };"
+ "class A : public Z { int b; };",
+ "A",
+ "class A : public Z {\n}"));
+ // Should be: with semicolon, with { ... }
+}
+
+TEST(DeclPrinter, TestCXXRecordDecl7) {
+ ASSERT_TRUE(PrintedDeclMatches(
+ "class Z { int a; };"
+ "class A : protected Z { int b; };",
+ "A",
+ "class A : protected Z {\n}"));
+ // Should be: with semicolon, with { ... }
+}
+
+TEST(DeclPrinter, TestCXXRecordDecl8) {
+ ASSERT_TRUE(PrintedDeclMatches(
+ "class Z { int a; };"
+ "class A : private Z { int b; };",
+ "A",
+ "class A : private Z {\n}"));
+ // Should be: with semicolon, with { ... }
+}
+
+TEST(DeclPrinter, TestCXXRecordDecl9) {
+ ASSERT_TRUE(PrintedDeclMatches(
+ "class Z { int a; };"
+ "class A : virtual Z { int b; };",
+ "A",
+ "class A : virtual Z {\n}"));
+ // Should be: with semicolon, with { ... }, without two spaces
+}
+
+TEST(DeclPrinter, TestCXXRecordDecl10) {
+ ASSERT_TRUE(PrintedDeclMatches(
+ "class Z { int a; };"
+ "class A : virtual public Z { int b; };",
+ "A",
+ "class A : virtual public Z {\n}"));
+ // Should be: with semicolon, with { ... }
+}
+
+TEST(DeclPrinter, TestCXXRecordDecl11) {
+ ASSERT_TRUE(PrintedDeclMatches(
+ "class Z { int a; };"
+ "class Y : virtual public Z { int b; };"
+ "class A : virtual public Z, private Y { int c; };",
+ "A",
+ "class A : virtual public Z, private Y {\n}"));
+ // Should be: with semicolon, with { ... }
+}
+
+TEST(DeclPrinter, TestFunctionDecl1) {
+ ASSERT_TRUE(PrintedDeclMatches(
+ "void A();",
+ "A",
+ "void A()"));
+ // Should be: with semicolon
+}
+
+TEST(DeclPrinter, TestFunctionDecl2) {
+ ASSERT_TRUE(PrintedDeclMatches(
+ "extern void A();",
+ "A",
+ "extern void A()"));
+ // Should be: with semicolon
+}
+
+TEST(DeclPrinter, TestFunctionDecl3) {
+ ASSERT_TRUE(PrintedDeclMatches(
+ "static void A();",
+ "A",
+ "static void A()"));
+ // Should be: with semicolon
+}
+
+TEST(DeclPrinter, TestFunctionDecl4) {
+ ASSERT_TRUE(PrintedDeclMatches(
+ "inline void A();",
+ "A",
+ "inline void A()"));
+ // Should be: with semicolon
+}
+
+TEST(DeclPrinter, TestFunctionDecl5) {
+ ASSERT_TRUE(PrintedDeclCXX11Matches(
+ "constexpr int A(int a);",
+ "A",
+ "int A(int a)"));
+ // WRONG; Should be: "constexpr int A(int a);"
+}
+
+TEST(DeclPrinter, TestFunctionDecl6) {
+ ASSERT_TRUE(PrintedDeclMatches(
+ "void A(int a);",
+ "A",
+ "void A(int a)"));
+ // Should be: with semicolon
+}
+
+TEST(DeclPrinter, TestFunctionDecl7) {
+ ASSERT_TRUE(PrintedDeclMatches(
+ "void A(...);",
+ "A",
+ "void A(...)"));
+ // Should be: with semicolon
+}
+
+TEST(DeclPrinter, TestFunctionDecl8) {
+ ASSERT_TRUE(PrintedDeclMatches(
+ "void A(int a, ...);",
+ "A",
+ "void A(int a, ...)"));
+ // Should be: with semicolon
+}
+
+TEST(DeclPrinter, TestFunctionDecl9) {
+ ASSERT_TRUE(PrintedDeclMatches(
+ "typedef long size_t;"
+ "typedef int *pInt;"
+ "void A(int a, pInt b, size_t c);",
+ "A",
+ "void A(int a, pInt b, size_t c)"));
+ // Should be: with semicolon
+}
+
+TEST(DeclPrinter, TestFunctionDecl10) {
+ ASSERT_TRUE(PrintedDeclMatches(
+ "void A(int a, int b = 0);",
+ "A",
+ "void A(int a, int b = 0)"));
+ // Should be: with semicolon
+}
+
+TEST(DeclPrinter, TestFunctionDecl11) {
+ ASSERT_TRUE(PrintedDeclMatches(
+ "void (*A(int a))(int b);",
+ "A",
+ "void (*A(int a))(int)"));
+ // Should be: with semicolon, with parameter name (?)
+}
+
+TEST(DeclPrinter, TestFunctionDecl12) {
+ ASSERT_TRUE(PrintedDeclMatches(
+ "template<typename T>"
+ "void A(T t) { }"
+ "template<>"
+ "void A(int N) { }",
+ function(hasName("A"), isExplicitTemplateSpecialization()).bind("id"),
+ "void A(int N) {\n}\n\n"));
+ // WRONG; Should be: "template <> void A(int N);"));
+}
+
+
+TEST(DeclPrinter, TestCXXConstructorDecl1) {
+ ASSERT_TRUE(PrintedDeclMatches(
+ "struct A {"
+ " A();"
+ "};",
+ constructor(ofClass(hasName("A"))).bind("id"),
+ ""));
+ // WRONG; Should be: "A();"
+}
+
+TEST(DeclPrinter, TestCXXConstructorDecl2) {
+ ASSERT_TRUE(PrintedDeclMatches(
+ "struct A {"
+ " A(int a);"
+ "};",
+ constructor(ofClass(hasName("A"))).bind("id"),
+ ""));
+ // WRONG; Should be: "A(int a);"
+}
+
+TEST(DeclPrinter, TestCXXConstructorDecl3) {
+ ASSERT_TRUE(PrintedDeclMatches(
+ "struct A {"
+ " A(const A &a);"
+ "};",
+ constructor(ofClass(hasName("A"))).bind("id"),
+ ""));
+ // WRONG; Should be: "A(const A &a);"
+}
+
+TEST(DeclPrinter, TestCXXConstructorDecl4) {
+ ASSERT_TRUE(PrintedDeclMatches(
+ "struct A {"
+ " A(const A &a, int = 0);"
+ "};",
+ constructor(ofClass(hasName("A"))).bind("id"),
+ ""));
+ // WRONG; Should be: "A(const A &a, int = 0);"
+}
+
+TEST(DeclPrinter, TestCXXConstructorDecl5) {
+ ASSERT_TRUE(PrintedDeclCXX11Matches(
+ "struct A {"
+ " A(const A &&a);"
+ "};",
+ constructor(ofClass(hasName("A"))).bind("id"),
+ ""));
+ // WRONG; Should be: "A(const A &&a);"
+}
+
+TEST(DeclPrinter, TestCXXConstructorDecl6) {
+ ASSERT_TRUE(PrintedDeclMatches(
+ "struct A {"
+ " explicit A(int a);"
+ "};",
+ constructor(ofClass(hasName("A"))).bind("id"),
+ ""));
+ // WRONG; Should be: "explicit A(int a);"
+}
+
+TEST(DeclPrinter, TestCXXConstructorDecl7) {
+ ASSERT_TRUE(PrintedDeclMatches(
+ "struct A {"
+ " constexpr A();"
+ "};",
+ ArrayRef<const char *>("-std=c++11"),
+ constructor(ofClass(hasName("A"))).bind("id"),
+ ""));
+ // WRONG; Should be: "constexpr A();"
+}
+
+TEST(DeclPrinter, TestCXXConstructorDecl8) {
+ ASSERT_TRUE(PrintedDeclMatches(
+ "struct A {"
+ " A() = default;"
+ "};",
+ ArrayRef<const char *>("-std=c++11"),
+ constructor(ofClass(hasName("A"))).bind("id"),
+ ""));
+ // WRONG; Should be: "A() = default;"
+}
+
+TEST(DeclPrinter, TestCXXConstructorDecl9) {
+ ASSERT_TRUE(PrintedDeclMatches(
+ "struct A {"
+ " A() = delete;"
+ "};",
+ ArrayRef<const char *>("-std=c++11"),
+ constructor(ofClass(hasName("A"))).bind("id"),
+ " = delete"));
+ // WRONG; Should be: "A() = delete;"
+}
+
+TEST(DeclPrinter, TestCXXDestructorDecl1) {
+ ASSERT_TRUE(PrintedDeclMatches(
+ "struct A {"
+ " ~A();"
+ "};",
+ destructor(ofClass(hasName("A"))).bind("id"),
+ "void ~A()"));
+ // WRONG; Should be: "~A();"
+}
+
+TEST(DeclPrinter, TestCXXDestructorDecl2) {
+ ASSERT_TRUE(PrintedDeclMatches(
+ "struct A {"
+ " virtual ~A();"
+ "};",
+ destructor(ofClass(hasName("A"))).bind("id"),
+ "virtual void ~A()"));
+ // WRONG; Should be: "virtual ~A();"
+}
+
+TEST(DeclPrinter, TestCXXConversionDecl1) {
+ ASSERT_TRUE(PrintedDeclMatches(
+ "struct A {"
+ " operator int();"
+ "};",
+ method(ofClass(hasName("A"))).bind("id"),
+ "int operator int()"));
+ // WRONG; Should be: "operator int();"
+}
+
+TEST(DeclPrinter, TestCXXConversionDecl2) {
+ ASSERT_TRUE(PrintedDeclMatches(
+ "struct A {"
+ " operator bool();"
+ "};",
+ method(ofClass(hasName("A"))).bind("id"),
+ "bool operator _Bool()"));
+ // WRONG; Should be: "operator bool();"
+}
+
+TEST(DeclPrinter, TestCXXConversionDecl3) {
+ ASSERT_TRUE(PrintedDeclMatches(
+ "struct Z {};"
+ "struct A {"
+ " operator Z();"
+ "};",
+ method(ofClass(hasName("A"))).bind("id"),
+ "Z operator struct Z()"));
+ // WRONG; Should be: "operator Z();"
+}
+
+TEST(DeclPrinter, TestCXXMethodDecl_AllocationFunction1) {
+ ASSERT_TRUE(PrintedDeclMatches(
+ "namespace std { typedef decltype(sizeof(int)) size_t; }"
+ "struct Z {"
+ " void *operator new(std::size_t);"
+ "};",
+ ArrayRef<const char *>("-std=c++11"),
+ method(ofClass(hasName("Z"))).bind("id"),
+ "void *operator new(std::size_t)"));
+ // Should be: with semicolon
+}
+
+TEST(DeclPrinter, TestCXXMethodDecl_AllocationFunction2) {
+ ASSERT_TRUE(PrintedDeclMatches(
+ "namespace std { typedef decltype(sizeof(int)) size_t; }"
+ "struct Z {"
+ " void *operator new[](std::size_t);"
+ "};",
+ ArrayRef<const char *>("-std=c++11"),
+ method(ofClass(hasName("Z"))).bind("id"),
+ "void *operator new[](std::size_t)"));
+ // Should be: with semicolon
+}
+
+TEST(DeclPrinter, TestCXXMethodDecl_AllocationFunction3) {
+ ASSERT_TRUE(PrintedDeclMatches(
+ "struct Z {"
+ " void operator delete(void *);"
+ "};",
+ ArrayRef<const char *>("-std=c++11"),
+ method(ofClass(hasName("Z"))).bind("id"),
+ "void operator delete(void *) noexcept"));
+ // Should be: with semicolon, without noexcept?
+}
+
+TEST(DeclPrinter, TestCXXMethodDecl_AllocationFunction4) {
+ ASSERT_TRUE(PrintedDeclMatches(
+ "struct Z {"
+ " void operator delete(void *);"
+ "};",
+ method(ofClass(hasName("Z"))).bind("id"),
+ "void operator delete(void *)"));
+ // Should be: with semicolon
+}
+
+TEST(DeclPrinter, TestCXXMethodDecl_AllocationFunction5) {
+ ASSERT_TRUE(PrintedDeclMatches(
+ "struct Z {"
+ " void operator delete[](void *);"
+ "};",
+ ArrayRef<const char *>("-std=c++11"),
+ method(ofClass(hasName("Z"))).bind("id"),
+ "void operator delete[](void *) noexcept"));
+ // Should be: with semicolon, without noexcept?
+}
+
+TEST(DeclPrinter, TestCXXMethodDecl_Operator1) {
+ const char *OperatorNames[] = {
+ "+", "-", "*", "/", "%", "^", "&", "|",
+ "=", "<", ">", "+=", "-=", "*=", "/=", "%=",
+ "^=", "&=", "|=", "<<", ">>", ">>=", "<<=", "==", "!=",
+ "<=", ">=", "&&", "||", ",", "->*",
+ "()", "[]"
+ };
+
+ for (unsigned i = 0, e = llvm::array_lengthof(OperatorNames); i != e; ++i) {
+ SmallString<128> Code;
+ Code.append("struct Z { void operator");
+ Code.append(OperatorNames[i]);
+ Code.append("(Z z); };");
+
+ SmallString<128> Expected;
+ Expected.append("void operator");
+ Expected.append(OperatorNames[i]);
+ Expected.append("(Z z)");
+ // Should be: with semicolon
+
+ ASSERT_TRUE(PrintedDeclMatches(
+ Code,
+ method(ofClass(hasName("Z"))).bind("id"),
+ Expected));
+ }
+}
+
+TEST(DeclPrinter, TestCXXMethodDecl_Operator2) {
+ const char *OperatorNames[] = {
+ "~", "!", "++", "--", "->"
+ };
+
+ for (unsigned i = 0, e = llvm::array_lengthof(OperatorNames); i != e; ++i) {
+ SmallString<128> Code;
+ Code.append("struct Z { void operator");
+ Code.append(OperatorNames[i]);
+ Code.append("(); };");
+
+ SmallString<128> Expected;
+ Expected.append("void operator");
+ Expected.append(OperatorNames[i]);
+ Expected.append("()");
+ // Should be: with semicolon
+
+ ASSERT_TRUE(PrintedDeclMatches(
+ Code,
+ method(ofClass(hasName("Z"))).bind("id"),
+ Expected));
+ }
+}
+
+TEST(DeclPrinter, TestCXXMethodDecl1) {
+ ASSERT_TRUE(PrintedDeclMatches(
+ "struct Z {"
+ " void A(int a);"
+ "};",
+ "A",
+ "void A(int a)"));
+ // Should be: with semicolon
+}
+
+TEST(DeclPrinter, TestCXXMethodDecl2) {
+ ASSERT_TRUE(PrintedDeclMatches(
+ "struct Z {"
+ " virtual void A(int a);"
+ "};",
+ "A",
+ "virtual void A(int a)"));
+ // Should be: with semicolon
+}
+
+TEST(DeclPrinter, TestCXXMethodDecl3) {
+ ASSERT_TRUE(PrintedDeclMatches(
+ "struct Z {"
+ " virtual void A(int a);"
+ "};"
+ "struct ZZ : Z {"
+ " void A(int a);"
+ "};",
+ "ZZ::A",
+ "void A(int a)"));
+ // Should be: with semicolon
+ // TODO: should we print "virtual"?
+}
+
+TEST(DeclPrinter, TestCXXMethodDecl4) {
+ ASSERT_TRUE(PrintedDeclMatches(
+ "struct Z {"
+ " inline void A(int a);"
+ "};",
+ "A",
+ "inline void A(int a)"));
+ // Should be: with semicolon
+}
+
+TEST(DeclPrinter, TestCXXMethodDecl5) {
+ ASSERT_TRUE(PrintedDeclMatches(
+ "struct Z {"
+ " virtual void A(int a) = 0;"
+ "};",
+ "A",
+ "virtual void A(int a) = 0"));
+ // Should be: with semicolon
+}
+
+TEST(DeclPrinter, TestCXXMethodDecl_CVQualifier1) {
+ ASSERT_TRUE(PrintedDeclMatches(
+ "struct Z {"
+ " void A(int a) const;"
+ "};",
+ "A",
+ "void A(int a) const"));
+ // Should be: with semicolon
+}
+
+TEST(DeclPrinter, TestCXXMethodDecl_CVQualifier2) {
+ ASSERT_TRUE(PrintedDeclMatches(
+ "struct Z {"
+ " void A(int a) volatile;"
+ "};",
+ "A",
+ "void A(int a) volatile"));
+ // Should be: with semicolon
+}
+
+TEST(DeclPrinter, TestCXXMethodDecl_CVQualifier3) {
+ ASSERT_TRUE(PrintedDeclMatches(
+ "struct Z {"
+ " void A(int a) const volatile;"
+ "};",
+ "A",
+ "void A(int a) const volatile"));
+ // Should be: with semicolon
+}
+
+TEST(DeclPrinter, TestCXXMethodDecl_RefQualifier1) {
+ ASSERT_TRUE(PrintedDeclCXX11Matches(
+ "struct Z {"
+ " void A(int a) &;"
+ "};",
+ "A",
+ "void A(int a)"));
+ // WRONG; Should be: "void A(int a) &;"
+}
+
+TEST(DeclPrinter, TestCXXMethodDecl_RefQualifier2) {
+ ASSERT_TRUE(PrintedDeclCXX11Matches(
+ "struct Z {"
+ " void A(int a) &&;"
+ "};",
+ "A",
+ "void A(int a)"));
+ // WRONG; Should be: "void A(int a) &&;"
+}
+
+TEST(DeclPrinter, TestFunctionDecl_ExceptionSpecification1) {
+ ASSERT_TRUE(PrintedDeclMatches(
+ "struct Z {"
+ " void A(int a) throw();"
+ "};",
+ "A",
+ "void A(int a) throw()"));
+ // Should be: with semicolon
+}
+
+TEST(DeclPrinter, TestFunctionDecl_ExceptionSpecification2) {
+ ASSERT_TRUE(PrintedDeclMatches(
+ "struct Z {"
+ " void A(int a) throw(int);"
+ "};",
+ "A",
+ "void A(int a) throw(int)"));
+ // Should be: with semicolon
+}
+
+TEST(DeclPrinter, TestFunctionDecl_ExceptionSpecification3) {
+ ASSERT_TRUE(PrintedDeclMatches(
+ "class ZZ {};"
+ "struct Z {"
+ " void A(int a) throw(ZZ, int);"
+ "};",
+ "A",
+ "void A(int a) throw(ZZ, int)"));
+ // Should be: with semicolon
+}
+
+TEST(DeclPrinter, TestFunctionDecl_ExceptionSpecification4) {
+ ASSERT_TRUE(PrintedDeclCXX11Matches(
+ "struct Z {"
+ " void A(int a) noexcept;"
+ "};",
+ "A",
+ "void A(int a) noexcept"));
+ // Should be: with semicolon
+}
+
+TEST(DeclPrinter, TestFunctionDecl_ExceptionSpecification5) {
+ ASSERT_TRUE(PrintedDeclCXX11Matches(
+ "struct Z {"
+ " void A(int a) noexcept(true);"
+ "};",
+ "A",
+ "void A(int a) noexcept(trueA(int a) noexcept(true)"));
+ // WRONG; Should be: "void A(int a) noexcept(true);"
+}
+
+TEST(DeclPrinter, TestFunctionDecl_ExceptionSpecification6) {
+ ASSERT_TRUE(PrintedDeclCXX11Matches(
+ "struct Z {"
+ " void A(int a) noexcept(1 < 2);"
+ "};",
+ "A",
+ "void A(int a) noexcept(1 < 2A(int a) noexcept(1 < 2)"));
+ // WRONG; Should be: "void A(int a) noexcept(1 < 2);"
+}
+
+TEST(DeclPrinter, TestFunctionDecl_ExceptionSpecification7) {
+ ASSERT_TRUE(PrintedDeclCXX11Matches(
+ "template<int N>"
+ "struct Z {"
+ " void A(int a) noexcept(N < 2);"
+ "};",
+ "A",
+ "void A(int a) noexcept(N < 2A(int a) noexcept(N < 2)"));
+ // WRONG; Should be: "void A(int a) noexcept(N < 2);"
+}
+
+TEST(DeclPrinter, TestVarDecl1) {
+ ASSERT_TRUE(PrintedDeclMatches(
+ "char *const (*(*A)[5])(int);",
+ "A",
+ "char *const (*(*A)[5])(int)"));
+ // Should be: with semicolon
+}
+
+TEST(DeclPrinter, TestVarDecl2) {
+ ASSERT_TRUE(PrintedDeclMatches(
+ "void (*A)() throw(int);",
+ "A",
+ "void (*A)() throw(int)"));
+ // Should be: with semicolon
+}
+
+TEST(DeclPrinter, TestVarDecl3) {
+ ASSERT_TRUE(PrintedDeclCXX11Matches(
+ "void (*A)() noexcept;",
+ "A",
+ "void (*A)() noexcept"));
+ // Should be: with semicolon
+}
+
+TEST(DeclPrinter, TestFieldDecl1) {
+ ASSERT_TRUE(PrintedDeclMatches(
+ "template<typename T>"
+ "struct Z { T A; };",
+ "A",
+ "T A"));
+ // Should be: with semicolon
+}
+
+TEST(DeclPrinter, TestFieldDecl2) {
+ ASSERT_TRUE(PrintedDeclMatches(
+ "template<int N>"
+ "struct Z { int A[N]; };",
+ "A",
+ "int A[N]"));
+ // Should be: with semicolon
+}
+
+TEST(DeclPrinter, TestClassTemplateDecl1) {
+ ASSERT_TRUE(PrintedDeclMatches(
+ "template<typename T>"
+ "struct A { T a; };",
+ classTemplate(hasName("A")).bind("id"),
+ "template <typename T> struct A {\n}"));
+ // Should be: with semicolon, with { ... }
+}
+
+TEST(DeclPrinter, TestClassTemplateDecl2) {
+ ASSERT_TRUE(PrintedDeclMatches(
+ "template<typename T = int>"
+ "struct A { T a; };",
+ classTemplate(hasName("A")).bind("id"),
+ "template <typename T = int> struct A {\n}"));
+ // Should be: with semicolon, with { ... }
+}
+
+TEST(DeclPrinter, TestClassTemplateDecl3) {
+ ASSERT_TRUE(PrintedDeclMatches(
+ "template<class T>"
+ "struct A { T a; };",
+ classTemplate(hasName("A")).bind("id"),
+ "template <class T> struct A {\n}"));
+ // Should be: with semicolon, with { ... }
+}
+
+TEST(DeclPrinter, TestClassTemplateDecl4) {
+ ASSERT_TRUE(PrintedDeclMatches(
+ "template<typename T, typename U>"
+ "struct A { T a; U b; };",
+ classTemplate(hasName("A")).bind("id"),
+ "template <typename T, typename U> struct A {\n}"));
+ // Should be: with semicolon, with { ... }
+}
+
+TEST(DeclPrinter, TestClassTemplateDecl5) {
+ ASSERT_TRUE(PrintedDeclMatches(
+ "template<int N>"
+ "struct A { int a[N]; };",
+ classTemplate(hasName("A")).bind("id"),
+ "template <int N> struct A {\n}"));
+ // Should be: with semicolon, with { ... }
+}
+
+TEST(DeclPrinter, TestClassTemplateDecl6) {
+ ASSERT_TRUE(PrintedDeclMatches(
+ "template<int N = 42>"
+ "struct A { int a[N]; };",
+ classTemplate(hasName("A")).bind("id"),
+ "template <int N = 42> struct A {\n}"));
+ // Should be: with semicolon, with { ... }
+}
+
+TEST(DeclPrinter, TestClassTemplateDecl7) {
+ ASSERT_TRUE(PrintedDeclMatches(
+ "typedef int MyInt;"
+ "template<MyInt N>"
+ "struct A { int a[N]; };",
+ classTemplate(hasName("A")).bind("id"),
+ "template <MyInt N> struct A {\n}"));
+ // Should be: with semicolon, with { ... }
+}
+
+TEST(DeclPrinter, TestClassTemplateDecl8) {
+ ASSERT_TRUE(PrintedDeclMatches(
+ "template<template<typename U> class T> struct A { };",
+ classTemplate(hasName("A")).bind("id"),
+ "template <template <typename U> class T> struct A {\n}"));
+ // Should be: with semicolon, with { ... }
+}
+
+TEST(DeclPrinter, TestClassTemplateDecl9) {
+ ASSERT_TRUE(PrintedDeclMatches(
+ "template<typename T> struct Z { };"
+ "template<template<typename U> class T = Z> struct A { };",
+ classTemplate(hasName("A")).bind("id"),
+ "template <template <typename U> class T> struct A {\n}"));
+ // Should be: with semicolon, with { ... }
+}
+
+TEST(DeclPrinter, TestClassTemplateDecl10) {
+ ASSERT_TRUE(PrintedDeclCXX11Matches(
+ "template<typename... T>"
+ "struct A { int a; };",
+ classTemplate(hasName("A")).bind("id"),
+ "template <typename ... T> struct A {\n}"));
+ // Should be: with semicolon, with { ... }, without spaces before '...'
+}
+
+TEST(DeclPrinter, TestClassTemplateDecl11) {
+ ASSERT_TRUE(PrintedDeclCXX11Matches(
+ "template<typename... T>"
+ "struct A : public T... { int a; };",
+ classTemplate(hasName("A")).bind("id"),
+ "template <typename ... T> struct A : public T... {\n}"));
+ // Should be: with semicolon, with { ... }, without spaces before '...'
+}
+
+TEST(DeclPrinter, TestClassTemplatePartialSpecializationDecl1) {
+ ASSERT_TRUE(PrintedDeclMatches(
+ "template<typename T, typename U>"
+ "struct A { T a; U b; };"
+ "template<typename T>"
+ "struct A<T, int> { T a; };",
+ classTemplateSpecialization().bind("id"),
+ "struct A {\n}"));
+ // WRONG; Should be: "template<typename T> struct A<T, int> { ... }"
+}
+
+TEST(DeclPrinter, TestClassTemplatePartialSpecializationDecl2) {
+ ASSERT_TRUE(PrintedDeclMatches(
+ "template<typename T>"
+ "struct A { T a; };"
+ "template<typename T>"
+ "struct A<T *> { T a; };",
+ classTemplateSpecialization().bind("id"),
+ "struct A {\n}"));
+ // WRONG; Should be: "template<typename T> struct A<T *> { ... }"
+}
+
+TEST(DeclPrinter, TestClassTemplateSpecializationDecl1) {
+ ASSERT_TRUE(PrintedDeclMatches(
+ "template<typename T>"
+ "struct A { T a; };"
+ "template<>"
+ "struct A<int> { int a; };",
+ classTemplateSpecialization().bind("id"),
+ "struct A {\n}"));
+ // WRONG; Should be: "template<> struct A<int> { ... }"
+}
+
+TEST(DeclPrinter, TestFunctionTemplateDecl1) {
+ ASSERT_TRUE(PrintedDeclMatches(
+ "template<typename T>"
+ "void A(T &t);",
+ functionTemplate(hasName("A")).bind("id"),
+ "template <typename T> void A(T &t)"));
+ // Should be: with semicolon
+}
+
+TEST(DeclPrinter, TestFunctionTemplateDecl2) {
+ ASSERT_TRUE(PrintedDeclMatches(
+ "template<typename T>"
+ "void A(T &t) { }",
+ functionTemplate(hasName("A")).bind("id"),
+ "template <typename T> void A(T &t) {\n}\n\n"));
+ // Should be: without body, with semicolon
+}
+
+TEST(DeclPrinter, TestFunctionTemplateDecl3) {
+ ASSERT_TRUE(PrintedDeclCXX11Matches(
+ "template<typename... T>"
+ "void A(T... a);",
+ functionTemplate(hasName("A")).bind("id"),
+ "template <typename ... T> void A(T a...)"));
+ // WRONG; Should be: "template <typename ... T> void A(T... a)"
+ // (not "T a...")
+ // Should be: with semicolon.
+}
+
+TEST(DeclPrinter, TestFunctionTemplateDecl4) {
+ ASSERT_TRUE(PrintedDeclMatches(
+ "struct Z { template<typename T> void A(T t); };",
+ functionTemplate(hasName("A")).bind("id"),
+ "template <typename T> void A(T t)"));
+ // Should be: with semicolon
+}
+
+TEST(DeclPrinter, TestFunctionTemplateDecl5) {
+ ASSERT_TRUE(PrintedDeclMatches(
+ "struct Z { template<typename T> void A(T t) {} };",
+ functionTemplate(hasName("A")).bind("id"),
+ "template <typename T> void A(T t) {\n}\n\n"));
+ // Should be: without body, with semicolon
+}
+
+TEST(DeclPrinter, TestFunctionTemplateDecl6) {
+ ASSERT_TRUE(PrintedDeclMatches(
+ "template<typename T >struct Z {"
+ " template<typename U> void A(U t) {}"
+ "};",
+ functionTemplate(hasName("A")).bind("id"),
+ "template <typename U> void A(U t) {\n}\n\n"));
+ // Should be: without body, with semicolon
+}
+
+TEST(DeclPrinter, TestTemplateArgumentList1) {
+ ASSERT_TRUE(PrintedDeclMatches(
+ "template<typename T> struct Z {};"
+ "struct X {};"
+ "Z<X> A;",
+ "A",
+ "Z<X> A"));
+ // Should be: with semicolon
+}
+
+TEST(DeclPrinter, TestTemplateArgumentList2) {
+ ASSERT_TRUE(PrintedDeclMatches(
+ "template<typename T, typename U> struct Z {};"
+ "struct X {};"
+ "typedef int Y;"
+ "Z<X, Y> A;",
+ "A",
+ "Z<X, Y> A"));
+ // Should be: with semicolon
+}
+
+TEST(DeclPrinter, TestTemplateArgumentList3) {
+ ASSERT_TRUE(PrintedDeclMatches(
+ "template<typename T> struct Z {};"
+ "template<typename T> struct X {};"
+ "Z<X<int> > A;",
+ "A",
+ "Z<X<int> > A"));
+ // Should be: with semicolon
+}
+
+TEST(DeclPrinter, TestTemplateArgumentList4) {
+ ASSERT_TRUE(PrintedDeclCXX11Matches(
+ "template<typename T> struct Z {};"
+ "template<typename T> struct X {};"
+ "Z<X<int>> A;",
+ "A",
+ "Z<X<int> > A"));
+ // Should be: with semicolon, without extra space in "> >"
+}
+
+TEST(DeclPrinter, TestTemplateArgumentList5) {
+ ASSERT_TRUE(PrintedDeclCXX11Matches(
+ "template<typename T> struct Z {};"
+ "template<typename T> struct X { Z<T> A; };",
+ "A",
+ "Z<T> A"));
+ // Should be: with semicolon
+}
+
+TEST(DeclPrinter, TestTemplateArgumentList6) {
+ ASSERT_TRUE(PrintedDeclMatches(
+ "template<template<typename T> class U> struct Z {};"
+ "template<typename T> struct X {};"
+ "Z<X> A;",
+ "A",
+ "Z<X> A"));
+ // Should be: with semicolon
+}
+
+TEST(DeclPrinter, TestTemplateArgumentList7) {
+ ASSERT_TRUE(PrintedDeclCXX11Matches(
+ "template<template<typename T> class U> struct Z {};"
+ "template<template<typename T> class U> struct Y {"
+ " Z<U> A;"
+ "};",
+ "A",
+ "Z<U> A"));
+ // Should be: with semicolon
+}
+
+TEST(DeclPrinter, TestTemplateArgumentList8) {
+ ASSERT_TRUE(PrintedDeclCXX11Matches(
+ "template<typename T> struct Z {};"
+ "template<template<typename T> class U> struct Y {"
+ " Z<U<int> > A;"
+ "};",
+ "A",
+ "Z<U<int> > A"));
+ // Should be: with semicolon
+}
+
+TEST(DeclPrinter, TestTemplateArgumentList9) {
+ ASSERT_TRUE(PrintedDeclMatches(
+ "template<unsigned I> struct Z {};"
+ "Z<0> A;",
+ "A",
+ "Z<0> A"));
+ // Should be: with semicolon
+}
+
+TEST(DeclPrinter, TestTemplateArgumentList10) {
+ ASSERT_TRUE(PrintedDeclMatches(
+ "template<unsigned I> struct Z {};"
+ "template<unsigned I> struct X { Z<I> A; };",
+ "A",
+ "Z<I> A"));
+ // Should be: with semicolon
+}
+
+TEST(DeclPrinter, TestTemplateArgumentList11) {
+ ASSERT_TRUE(PrintedDeclMatches(
+ "template<int I> struct Z {};"
+ "Z<42 * 10 - 420 / 1> A;",
+ "A",
+ "Z<42 * 10 - 420 / 1> A"));
+ // Should be: with semicolon
+}
+
+TEST(DeclPrinter, TestTemplateArgumentList12) {
+ ASSERT_TRUE(PrintedDeclMatches(
+ "template<const char *p> struct Z {};"
+ "extern const char X[] = \"aaa\";"
+ "Z<X> A;",
+ "A",
+ "Z<X> A"));
+ // Should be: with semicolon
+}
+
+TEST(DeclPrinter, TestTemplateArgumentList13) {
+ ASSERT_TRUE(PrintedDeclCXX11Matches(
+ "template<typename... T> struct Z {};"
+ "template<typename... T> struct X {"
+ " Z<T...> A;"
+ "};",
+ "A",
+ "Z<T...> A"));
+ // Should be: with semicolon, without extra space in "> >"
+}
+
+TEST(DeclPrinter, TestTemplateArgumentList14) {
+ ASSERT_TRUE(PrintedDeclCXX11Matches(
+ "template<typename... T> struct Z {};"
+ "template<typename T> struct Y {};"
+ "template<typename... T> struct X {"
+ " Z<Y<T>...> A;"
+ "};",
+ "A",
+ "Z<Y<T>...> A"));
+ // Should be: with semicolon, without extra space in "> >"
+}
+
+TEST(DeclPrinter, TestTemplateArgumentList15) {
+ ASSERT_TRUE(PrintedDeclCXX11Matches(
+ "template<unsigned I> struct Z {};"
+ "template<typename... T> struct X {"
+ " Z<sizeof...(T)> A;"
+ "};",
+ "A",
+ "Z<sizeof...(T)> A"));
+ // Should be: with semicolon, without extra space in "> >"
+}
+
Modified: cfe/trunk/unittests/AST/Makefile
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/AST/Makefile?rev=162245&r1=162244&r2=162245&view=diff
==============================================================================
--- cfe/trunk/unittests/AST/Makefile (original)
+++ cfe/trunk/unittests/AST/Makefile Mon Aug 20 18:39:06 2012
@@ -9,7 +9,10 @@
CLANG_LEVEL = ../..
TESTNAME = AST
-LINK_COMPONENTS := support mc
-USEDLIBS = clangAST.a clangLex.a clangBasic.a
+include $(CLANG_LEVEL)/../../Makefile.config
+LINK_COMPONENTS := $(TARGETS_TO_BUILD) asmparser support mc
+USEDLIBS = clangTooling.a clangFrontend.a clangSerialization.a clangDriver.a \
+ clangRewrite.a clangParse.a clangSema.a clangAnalysis.a \
+ clangAST.a clangASTMatchers.a clangLex.a clangBasic.a clangEdit.a
include $(CLANG_LEVEL)/unittests/Makefile
More information about the cfe-commits
mailing list