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:
PrintMatch(bool suppressUnwrittenScope)37 explicit PrintMatch(bool suppressUnwrittenScope)
38 : NumFoundDecls(0), SuppressUnwrittenScope(suppressUnwrittenScope) {}
39
run(const MatchFinder::MatchResult & Result)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
getPrinted() const54 StringRef getPrinted() const {
55 return Printed;
56 }
57
getNumFoundDecls() const58 unsigned getNumFoundDecls() const {
59 return NumFoundDecls;
60 }
61 };
62
63 ::testing::AssertionResult
PrintedNamedDeclMatches(StringRef Code,const std::vector<std::string> & Args,bool SuppressUnwrittenScope,const DeclarationMatcher & NodeMatch,StringRef ExpectedPrinted,StringRef FileName)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
PrintedNamedDeclCXX98Matches(StringRef Code,StringRef DeclName,StringRef ExpectedPrinted)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
PrintedWrittenNamedDeclCXX11Matches(StringRef Code,StringRef DeclName,StringRef ExpectedPrinted)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
TEST(NamedDeclPrinter,TestNamespace1)121 TEST(NamedDeclPrinter, TestNamespace1) {
122 ASSERT_TRUE(PrintedNamedDeclCXX98Matches(
123 "namespace { int A; }",
124 "A",
125 "(anonymous namespace)::A"));
126 }
127
TEST(NamedDeclPrinter,TestNamespace2)128 TEST(NamedDeclPrinter, TestNamespace2) {
129 ASSERT_TRUE(PrintedWrittenNamedDeclCXX11Matches(
130 "inline namespace Z { namespace { int A; } }",
131 "A",
132 "A"));
133 }
134
TEST(NamedDeclPrinter,TestUnscopedUnnamedEnum)135 TEST(NamedDeclPrinter, TestUnscopedUnnamedEnum) {
136 ASSERT_TRUE(PrintedWrittenNamedDeclCXX11Matches(
137 "enum { A };",
138 "A",
139 "A"));
140 }
141
TEST(NamedDeclPrinter,TestNamedEnum)142 TEST(NamedDeclPrinter, TestNamedEnum) {
143 ASSERT_TRUE(PrintedWrittenNamedDeclCXX11Matches(
144 "enum X { A };",
145 "A",
146 "X::A"));
147 }
148
TEST(NamedDeclPrinter,TestScopedNamedEnum)149 TEST(NamedDeclPrinter, TestScopedNamedEnum) {
150 ASSERT_TRUE(PrintedWrittenNamedDeclCXX11Matches(
151 "enum class X { A };",
152 "A",
153 "X::A"));
154 }
155
TEST(NamedDeclPrinter,TestClassWithUnscopedUnnamedEnum)156 TEST(NamedDeclPrinter, TestClassWithUnscopedUnnamedEnum) {
157 ASSERT_TRUE(PrintedWrittenNamedDeclCXX11Matches(
158 "class X { enum { A }; };",
159 "A",
160 "X::A"));
161 }
162
TEST(NamedDeclPrinter,TestClassWithUnscopedNamedEnum)163 TEST(NamedDeclPrinter, TestClassWithUnscopedNamedEnum) {
164 ASSERT_TRUE(PrintedWrittenNamedDeclCXX11Matches(
165 "class X { enum Y { A }; };",
166 "A",
167 "X::Y::A"));
168 }
169
TEST(NamedDeclPrinter,TestClassWithScopedNamedEnum)170 TEST(NamedDeclPrinter, TestClassWithScopedNamedEnum) {
171 ASSERT_TRUE(PrintedWrittenNamedDeclCXX11Matches(
172 "class X { enum class Y { A }; };",
173 "A",
174 "X::Y::A"));
175 }
176