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