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   virtual void run(const MatchFinder::MatchResult &Result) {
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