1 //===- unittests/AST/NamedDeclPrinterTest.cpp --- NamedDecl printer tests -===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file contains tests for NamedDecl::printQualifiedName(). 11 // 12 // These tests have a coding convention: 13 // * declaration to be printed is named 'A' unless it should have some special 14 // name (e.g., 'operator+'); 15 // * additional helper declarations are 'Z', 'Y', 'X' and so on. 16 // 17 //===----------------------------------------------------------------------===// 18 19 #include "clang/AST/ASTContext.h" 20 #include "clang/ASTMatchers/ASTMatchFinder.h" 21 #include "clang/Tooling/Tooling.h" 22 #include "llvm/ADT/SmallString.h" 23 #include "gtest/gtest.h" 24 25 using namespace clang; 26 using namespace ast_matchers; 27 using namespace tooling; 28 29 namespace { 30 31 class PrintMatch : public MatchFinder::MatchCallback { 32 SmallString<1024> Printed; 33 unsigned NumFoundDecls; 34 bool SuppressUnwrittenScope; 35 36 public: 37 explicit PrintMatch(bool suppressUnwrittenScope) 38 : NumFoundDecls(0), SuppressUnwrittenScope(suppressUnwrittenScope) {} 39 40 void run(const MatchFinder::MatchResult &Result) override { 41 const NamedDecl *ND = Result.Nodes.getNodeAs<NamedDecl>("id"); 42 if (!ND) 43 return; 44 NumFoundDecls++; 45 if (NumFoundDecls > 1) 46 return; 47 48 llvm::raw_svector_ostream Out(Printed); 49 PrintingPolicy Policy = Result.Context->getPrintingPolicy(); 50 Policy.SuppressUnwrittenScope = SuppressUnwrittenScope; 51 ND->printQualifiedName(Out, Policy); 52 } 53 54 StringRef getPrinted() const { 55 return Printed; 56 } 57 58 unsigned getNumFoundDecls() const { 59 return NumFoundDecls; 60 } 61 }; 62 63 ::testing::AssertionResult 64 PrintedNamedDeclMatches(StringRef Code, const std::vector<std::string> &Args, 65 bool SuppressUnwrittenScope, 66 const DeclarationMatcher &NodeMatch, 67 StringRef ExpectedPrinted, StringRef FileName) { 68 PrintMatch Printer(SuppressUnwrittenScope); 69 MatchFinder Finder; 70 Finder.addMatcher(NodeMatch, &Printer); 71 std::unique_ptr<FrontendActionFactory> Factory = 72 newFrontendActionFactory(&Finder); 73 74 if (!runToolOnCodeWithArgs(Factory->create(), Code, Args, FileName)) 75 return testing::AssertionFailure() 76 << "Parsing error in \"" << Code.str() << "\""; 77 78 if (Printer.getNumFoundDecls() == 0) 79 return testing::AssertionFailure() 80 << "Matcher didn't find any named declarations"; 81 82 if (Printer.getNumFoundDecls() > 1) 83 return testing::AssertionFailure() 84 << "Matcher should match only one named declaration " 85 "(found " << Printer.getNumFoundDecls() << ")"; 86 87 if (Printer.getPrinted() != ExpectedPrinted) 88 return ::testing::AssertionFailure() 89 << "Expected \"" << ExpectedPrinted.str() << "\", " 90 "got \"" << Printer.getPrinted().str() << "\""; 91 92 return ::testing::AssertionSuccess(); 93 } 94 95 ::testing::AssertionResult 96 PrintedNamedDeclCXX98Matches(StringRef Code, StringRef DeclName, 97 StringRef ExpectedPrinted) { 98 std::vector<std::string> Args(1, "-std=c++98"); 99 return PrintedNamedDeclMatches(Code, 100 Args, 101 /*SuppressUnwrittenScope*/ false, 102 namedDecl(hasName(DeclName)).bind("id"), 103 ExpectedPrinted, 104 "input.cc"); 105 } 106 107 ::testing::AssertionResult 108 PrintedWrittenNamedDeclCXX11Matches(StringRef Code, StringRef DeclName, 109 StringRef ExpectedPrinted) { 110 std::vector<std::string> Args(1, "-std=c++11"); 111 return PrintedNamedDeclMatches(Code, 112 Args, 113 /*SuppressUnwrittenScope*/ true, 114 namedDecl(hasName(DeclName)).bind("id"), 115 ExpectedPrinted, 116 "input.cc"); 117 } 118 119 } // unnamed namespace 120 121 TEST(NamedDeclPrinter, TestNamespace1) { 122 ASSERT_TRUE(PrintedNamedDeclCXX98Matches( 123 "namespace { int A; }", 124 "A", 125 "(anonymous namespace)::A")); 126 } 127 128 TEST(NamedDeclPrinter, TestNamespace2) { 129 ASSERT_TRUE(PrintedWrittenNamedDeclCXX11Matches( 130 "inline namespace Z { namespace { int A; } }", 131 "A", 132 "A")); 133 } 134 135 TEST(NamedDeclPrinter, TestUnscopedUnnamedEnum) { 136 ASSERT_TRUE(PrintedWrittenNamedDeclCXX11Matches( 137 "enum { A };", 138 "A", 139 "A")); 140 } 141 142 TEST(NamedDeclPrinter, TestNamedEnum) { 143 ASSERT_TRUE(PrintedWrittenNamedDeclCXX11Matches( 144 "enum X { A };", 145 "A", 146 "X::A")); 147 } 148 149 TEST(NamedDeclPrinter, TestScopedNamedEnum) { 150 ASSERT_TRUE(PrintedWrittenNamedDeclCXX11Matches( 151 "enum class X { A };", 152 "A", 153 "X::A")); 154 } 155 156 TEST(NamedDeclPrinter, TestClassWithUnscopedUnnamedEnum) { 157 ASSERT_TRUE(PrintedWrittenNamedDeclCXX11Matches( 158 "class X { enum { A }; };", 159 "A", 160 "X::A")); 161 } 162 163 TEST(NamedDeclPrinter, TestClassWithUnscopedNamedEnum) { 164 ASSERT_TRUE(PrintedWrittenNamedDeclCXX11Matches( 165 "class X { enum Y { A }; };", 166 "A", 167 "X::Y::A")); 168 } 169 170 TEST(NamedDeclPrinter, TestClassWithScopedNamedEnum) { 171 ASSERT_TRUE(PrintedWrittenNamedDeclCXX11Matches( 172 "class X { enum class Y { A }; };", 173 "A", 174 "X::Y::A")); 175 } 176