1 //===- unittests/AST/NamedDeclPrinterTest.cpp --- NamedDecl printer tests -===//
3 // 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
7 //===----------------------------------------------------------------------===//
9 // This file contains tests for NamedDecl::printQualifiedName().
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.
16 //===----------------------------------------------------------------------===//
19 #include "clang/AST/ASTContext.h"
20 #include "clang/AST/Decl.h"
21 #include "clang/AST/PrettyPrinter.h"
22 #include "clang/ASTMatchers/ASTMatchFinder.h"
23 #include "clang/Tooling/Tooling.h"
24 #include "llvm/ADT/SmallString.h"
25 #include "llvm/Support/raw_ostream.h"
26 #include "gtest/gtest.h"
28 using namespace clang
;
29 using namespace ast_matchers
;
30 using namespace tooling
;
34 class PrintMatch
: public MatchFinder::MatchCallback
{
35 SmallString
<1024> Printed
;
36 unsigned NumFoundDecls
;
37 std::function
<void(llvm::raw_ostream
&OS
, const NamedDecl
*)> Printer
;
41 std::function
<void(llvm::raw_ostream
&OS
, const NamedDecl
*)> Printer
)
42 : NumFoundDecls(0), Printer(std::move(Printer
)) {}
44 void run(const MatchFinder::MatchResult
&Result
) override
{
45 const NamedDecl
*ND
= Result
.Nodes
.getNodeAs
<NamedDecl
>("id");
49 if (NumFoundDecls
> 1)
52 llvm::raw_svector_ostream
Out(Printed
);
56 StringRef
getPrinted() const {
60 unsigned getNumFoundDecls() const {
65 ::testing::AssertionResult
PrintedDeclMatches(
66 StringRef Code
, const std::vector
<std::string
> &Args
,
67 const DeclarationMatcher
&NodeMatch
, StringRef ExpectedPrinted
,
69 std::function
<void(llvm::raw_ostream
&, const NamedDecl
*)> Print
) {
70 return PrintedNodeMatches
<NamedDecl
>(
71 Code
, Args
, NodeMatch
, ExpectedPrinted
, FileName
,
72 [Print
](llvm::raw_ostream
&Out
, const ASTContext
*Context
,
74 PrintingPolicyAdjuster PolicyAdjuster
) { Print(Out
, ND
); });
77 ::testing::AssertionResult
78 PrintedNamedDeclMatches(StringRef Code
, const std::vector
<std::string
> &Args
,
79 bool SuppressUnwrittenScope
,
80 const DeclarationMatcher
&NodeMatch
,
81 StringRef ExpectedPrinted
, StringRef FileName
) {
82 return PrintedDeclMatches(Code
, Args
, NodeMatch
, ExpectedPrinted
, FileName
,
83 [=](llvm::raw_ostream
&Out
, const NamedDecl
*ND
) {
85 ND
->getASTContext().getPrintingPolicy();
86 Policy
.SuppressUnwrittenScope
=
87 SuppressUnwrittenScope
;
88 ND
->printQualifiedName(Out
, Policy
);
92 ::testing::AssertionResult
93 PrintedNamedDeclCXX98Matches(StringRef Code
, StringRef DeclName
,
94 StringRef ExpectedPrinted
) {
95 std::vector
<std::string
> Args(1, "-std=c++98");
96 return PrintedNamedDeclMatches(Code
, Args
,
97 /*SuppressUnwrittenScope*/ false,
98 namedDecl(hasName(DeclName
)).bind("id"),
99 ExpectedPrinted
, "input.cc");
102 ::testing::AssertionResult
103 PrintedWrittenNamedDeclCXX11Matches(StringRef Code
, StringRef DeclName
,
104 StringRef ExpectedPrinted
) {
105 std::vector
<std::string
> Args(1, "-std=c++11");
106 return PrintedNamedDeclMatches(Code
, Args
,
107 /*SuppressUnwrittenScope*/ true,
108 namedDecl(hasName(DeclName
)).bind("id"),
109 ExpectedPrinted
, "input.cc");
112 ::testing::AssertionResult
113 PrintedWrittenPropertyDeclObjCMatches(StringRef Code
, StringRef DeclName
,
114 StringRef ExpectedPrinted
) {
115 std::vector
<std::string
> Args
{"-std=c++11", "-xobjective-c++"};
116 return PrintedNamedDeclMatches(Code
, Args
,
117 /*SuppressUnwrittenScope*/ true,
118 objcPropertyDecl(hasName(DeclName
)).bind("id"),
119 ExpectedPrinted
, "input.m");
122 ::testing::AssertionResult
123 PrintedNestedNameSpecifierMatches(StringRef Code
, StringRef DeclName
,
124 StringRef ExpectedPrinted
) {
125 std::vector
<std::string
> Args
{"-std=c++11"};
126 return PrintedDeclMatches(Code
, Args
, namedDecl(hasName(DeclName
)).bind("id"),
127 ExpectedPrinted
, "input.cc",
128 [](llvm::raw_ostream
&Out
, const NamedDecl
*D
) {
129 D
->printNestedNameSpecifier(Out
);
133 } // unnamed namespace
135 TEST(NamedDeclPrinter
, TestNamespace1
) {
136 ASSERT_TRUE(PrintedNamedDeclCXX98Matches(
137 "namespace { int A; }",
139 "(anonymous namespace)::A"));
142 TEST(NamedDeclPrinter
, TestNamespace2
) {
143 ASSERT_TRUE(PrintedWrittenNamedDeclCXX11Matches(
144 "inline namespace Z { namespace { int A; } }",
149 TEST(NamedDeclPrinter
, TestUnscopedUnnamedEnum
) {
150 ASSERT_TRUE(PrintedWrittenNamedDeclCXX11Matches(
156 TEST(NamedDeclPrinter
, TestNamedEnum
) {
157 ASSERT_TRUE(PrintedWrittenNamedDeclCXX11Matches(
163 TEST(NamedDeclPrinter
, TestScopedNamedEnum
) {
164 ASSERT_TRUE(PrintedWrittenNamedDeclCXX11Matches(
165 "enum class X { A };",
170 TEST(NamedDeclPrinter
, TestClassWithUnscopedUnnamedEnum
) {
171 ASSERT_TRUE(PrintedWrittenNamedDeclCXX11Matches(
172 "class X { enum { A }; };",
177 TEST(NamedDeclPrinter
, TestClassWithUnscopedNamedEnum
) {
178 ASSERT_TRUE(PrintedWrittenNamedDeclCXX11Matches(
179 "class X { enum Y { A }; };",
184 TEST(NamedDeclPrinter
, TestClassWithScopedNamedEnum
) {
185 ASSERT_TRUE(PrintedWrittenNamedDeclCXX11Matches(
186 "class X { enum class Y { A }; };",
191 TEST(NamedDeclPrinter
, TestLinkageInNamespace
) {
192 ASSERT_TRUE(PrintedWrittenNamedDeclCXX11Matches(
193 "namespace X { extern \"C\" { int A; } }",
198 TEST(NamedDeclPrinter
, TestObjCClassExtension
) {
205 @property(nonatomic) int property;
208 ASSERT_TRUE(PrintedWrittenPropertyDeclObjCMatches(
214 TEST(NamedDeclPrinter
, TestInstanceObjCClassExtension
) {
220 char data; // legal with non-fragile ABI.
225 std::vector
<std::string
> Args
{
226 "-std=c++11", "-xobjective-c++",
227 "-fobjc-runtime=macosx" /*force to use non-fragile ABI*/};
228 ASSERT_TRUE(PrintedNamedDeclMatches(Code
, Args
,
229 /*SuppressUnwrittenScope*/ true,
230 namedDecl(hasName("data")).bind("id"),
232 "ObjC::data", "input.mm"));
235 TEST(NamedDeclPrinter
, TestObjCClassExtensionWithGetter
) {
242 @property(nonatomic, getter=myPropertyGetter) int property;
245 ASSERT_TRUE(PrintedWrittenPropertyDeclObjCMatches(
251 TEST(NamedDeclPrinter
, NestedNameSpecifierSimple
) {
254 namespace foo { namespace bar { void func(); } }
256 ASSERT_TRUE(PrintedNestedNameSpecifierMatches(Code
, "func", "foo::bar::"));
259 TEST(NamedDeclPrinter
, NestedNameSpecifierTemplateArgs
) {
262 template <class T> struct vector;
263 template <> struct vector<int> { int method(); };
266 PrintedNestedNameSpecifierMatches(Code
, "method", "vector<int>::"));