xref: /llvm-project/clang/unittests/AST/ASTDumperTest.cpp (revision 8d1b1c9b97de557299e8148a79d756c1e8d9b7eb)
1 //===- unittests/AST/ASTDumperTest.cpp --- Test of AST node dump() methods ===//
2 //
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
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file contains tests for TypeLoc::dump() and related methods.
10 // Most of these are lit tests via clang -ast-dump. However some nodes are not
11 // included in dumps of (TranslationUnit)Decl, but still relevant when dumped
12 // directly.
13 //
14 //===----------------------------------------------------------------------===//
15 
16 #include "ASTPrint.h"
17 #include "clang/AST/ASTContext.h"
18 #include "clang/AST/Decl.h"
19 #include "clang/Testing/TestAST.h"
20 #include "llvm/ADT/StringRef.h"
21 #include "gmock/gmock.h"
22 #include "gtest/gtest.h"
23 
24 using namespace clang;
25 using namespace ast_matchers;
26 
27 namespace {
28 using testing::ElementsAre;
29 using testing::StartsWith;
30 
dumpTypeLoc(llvm::StringRef Name,ASTContext & Ctx)31 std::vector<std::string> dumpTypeLoc(llvm::StringRef Name, ASTContext &Ctx) {
32   auto Lookup = Ctx.getTranslationUnitDecl()->lookup(&Ctx.Idents.get(Name));
33   DeclaratorDecl *D = nullptr;
34   if ((D = Lookup.find_first<DeclaratorDecl>()))
35     ;
36   else if (auto *TD = Lookup.find_first<FunctionTemplateDecl>())
37     D = TD->getTemplatedDecl();
38   EXPECT_NE(D, nullptr) << Name;
39   if (!D)
40     return {};
41   EXPECT_NE(D->getTypeSourceInfo(), nullptr);
42   if (!D->getTypeSourceInfo())
43     return {};
44   std::string S;
45   {
46     llvm::raw_string_ostream OS(S);
47     D->getTypeSourceInfo()->getTypeLoc().dump(OS, Ctx);
48   }
49   // Split result into lines.
50   std::vector<std::string> Result;
51   auto Remaining = llvm::StringRef(S).trim("\n");
52   while (!Remaining.empty()) {
53     auto [First, Rest] = Remaining.split('\n');
54     Result.push_back(First.str());
55     Remaining = Rest;
56   }
57   return Result;
58 }
59 
TEST(ASTDumper,TypeLocChain)60 TEST(ASTDumper, TypeLocChain) {
61   TestAST AST(R"cc(
62     const int **x;
63   )cc");
64   EXPECT_THAT(
65       dumpTypeLoc("x", AST.context()),
66       ElementsAre(""
67                   "PointerTypeLoc <input.mm:2:11, col:16> 'const int **'",
68                   "`-PointerTypeLoc <col:11, col:15> 'const int *'",
69                   "  `-QualifiedTypeLoc <col:11> 'const int'",
70                   "    `-BuiltinTypeLoc <col:11> 'int'"));
71 }
72 
TEST(ASTDumper,AutoType)73 TEST(ASTDumper, AutoType) {
74   TestInputs Inputs(R"cc(
75     template <class, class> concept C = true;
76     C<int> auto str1 = "hello";
77     auto str2 = "hello";
78   )cc");
79   Inputs.ExtraArgs.push_back("-std=c++20");
80   TestAST AST(Inputs);
81   EXPECT_THAT(
82       dumpTypeLoc("str1", AST.context()),
83       ElementsAre(""
84                   "AutoTypeLoc <input.mm:3:5, col:12> 'C<int> auto' undeduced",
85                   StartsWith("|-Concept"), //
86                   "`-TemplateArgument <col:7> type 'int'",
87                   StartsWith("  `-BuiltinType")));
88   EXPECT_THAT(dumpTypeLoc("str2", AST.context()),
89               ElementsAre(""
90                           "AutoTypeLoc <input.mm:4:5> 'auto' undeduced"));
91 }
92 
93 
TEST(ASTDumper,FunctionTypeLoc)94 TEST(ASTDumper, FunctionTypeLoc) {
95   TestAST AST(R"cc(
96     void x(int, double *y);
97 
98     auto trailing() -> int;
99 
100     template <class T> int tmpl(T&&);
101   )cc");
102   EXPECT_THAT(
103       dumpTypeLoc("x", AST.context()),
104       ElementsAre(""
105                   "FunctionProtoTypeLoc <input.mm:2:5, col:26> 'void (int, "
106                   "double *)' cdecl",
107                   StartsWith("|-ParmVarDecl"),
108                   "| `-BuiltinTypeLoc <col:12> 'int'",
109                   StartsWith("|-ParmVarDecl"),
110                   "| `-PointerTypeLoc <col:17, col:24> 'double *'",
111                   "|   `-BuiltinTypeLoc <col:17> 'double'",
112                   "`-BuiltinTypeLoc <col:5> 'void'"));
113 
114   EXPECT_THAT(dumpTypeLoc("trailing", AST.context()),
115               ElementsAre(""
116                           "FunctionProtoTypeLoc <input.mm:4:5, col:24> "
117                           "'auto () -> int' trailing_return cdecl",
118                           "`-BuiltinTypeLoc <col:24> 'int'"));
119 
120   EXPECT_THAT(
121       dumpTypeLoc("tmpl", AST.context()),
122       ElementsAre(""
123                   "FunctionProtoTypeLoc <input.mm:6:24, col:36> "
124                   "'int (T &&)' cdecl",
125                   StartsWith("|-ParmVarDecl"),
126                   "| `-RValueReferenceTypeLoc <col:33, col:34> 'T &&'",
127                   "|   `-TemplateTypeParmTypeLoc <col:33> 'T' depth 0 index 0",
128                   StartsWith("|     `-TemplateTypeParm"),
129                   "`-BuiltinTypeLoc <col:24> 'int'"));
130 
131   // Dynamic-exception-spec needs C++14 or earlier.
132   TestInputs Throws(R"cc(
133     void throws() throw(int);
134   )cc");
135   Throws.ExtraArgs.push_back("-std=c++14");
136   AST = TestAST(Throws);
137   EXPECT_THAT(dumpTypeLoc("throws", AST.context()),
138               ElementsAre(""
139                           "FunctionProtoTypeLoc <input.mm:2:5, col:28> "
140                           "'void () throw(int)' exceptionspec_dynamic cdecl",
141                           // FIXME: include TypeLoc for int
142                           "|-Exceptions: 'int'",
143                           "`-BuiltinTypeLoc <col:5> 'void'"));
144 }
145 
146 } // namespace
147