clang-tools 20.0.0git
DumpASTTests.cpp
Go to the documentation of this file.
1//===-- DumpASTTests.cpp --------------------------------------------------===//
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#include "Annotations.h"
10#include "DumpAST.h"
11#include "TestTU.h"
12#include "clang/AST/ASTTypeTraits.h"
13#include "llvm/Support/ScopedPrinter.h"
14#include "gmock/gmock.h"
15#include "gtest/gtest.h"
16
17namespace clang {
18namespace clangd {
19namespace {
20using testing::Contains;
21using testing::Not;
22using testing::SizeIs;
23
24MATCHER_P(withDetail, str, "") { return arg.detail == str; }
25
26TEST(DumpASTTests, BasicInfo) {
27 std::pair</*Code=*/std::string, /*Expected=*/std::string> Cases[] = {
28 {R"cpp(
29float root(int *x) {
30 return *x + 1;
31}
32 )cpp",
33 R"(
34declaration: Function - root
35 type: FunctionProto
36 type: Builtin - float
37 declaration: ParmVar - x
38 type: Pointer
39 type: Builtin - int
40 statement: Compound
41 statement: Return
42 expression: ImplicitCast - IntegralToFloating
43 expression: BinaryOperator - +
44 expression: ImplicitCast - LValueToRValue
45 expression: UnaryOperator - *
46 expression: ImplicitCast - LValueToRValue
47 expression: DeclRef - x
48 expression: IntegerLiteral - 1
49 )"},
50 {R"cpp(
51namespace root {
52struct S { static const int x = 0; ~S(); };
53int y = S::x + root::S().x;
54}
55 )cpp",
56 R"(
57declaration: Namespace - root
58 declaration: CXXRecord - S
59 declaration: Var - x
60 type: Qualified - const
61 type: Builtin - int
62 expression: IntegerLiteral - 0
63 declaration: CXXDestructor
64 type: Record - S
65 type: FunctionProto
66 type: Builtin - void
67 declaration: CXXConstructor
68 declaration: CXXConstructor
69 declaration: Var - y
70 type: Builtin - int
71 expression: ExprWithCleanups
72 expression: BinaryOperator - +
73 expression: ImplicitCast - LValueToRValue
74 expression: DeclRef - x
75 specifier: TypeSpec
76 type: Record - S
77 expression: ImplicitCast - LValueToRValue
78 expression: Member - x
79 expression: CXXBindTemporary
80 expression: CXXTemporaryObject - S
81 type: Elaborated
82 specifier: Namespace - root::
83 type: Record - S
84 )"},
85 {R"cpp(
86namespace root {
87struct S { static const int x = 0; };
88int y = S::x + root::S().x;
89}
90 )cpp",
91 R"(
92declaration: Namespace - root
93 declaration: CXXRecord - S
94 declaration: Var - x
95 type: Qualified - const
96 type: Builtin - int
97 expression: IntegerLiteral - 0
98 declaration: CXXConstructor
99 declaration: CXXConstructor
100 declaration: CXXConstructor
101 declaration: CXXDestructor
102 declaration: Var - y
103 type: Builtin - int
104 expression: BinaryOperator - +
105 expression: ImplicitCast - LValueToRValue
106 expression: DeclRef - x
107 specifier: TypeSpec
108 type: Record - S
109 expression: ImplicitCast - LValueToRValue
110 expression: Member - x
111 expression: CXXTemporaryObject - S
112 type: Elaborated
113 specifier: Namespace - root::
114 type: Record - S
115 )"},
116 {R"cpp(
117namespace root {
118template <typename T> int tmpl() {
119 (void)tmpl<unsigned>();
120 return T::value;
121}
122}
123 )cpp",
124 R"(
125declaration: Namespace - root
126 declaration: FunctionTemplate - tmpl
127 declaration: TemplateTypeParm - T
128 declaration: Function - tmpl
129 type: FunctionProto
130 type: Builtin - int
131 statement: Compound
132 expression: CStyleCast - ToVoid
133 type: Builtin - void
134 expression: Call
135 expression: ImplicitCast - FunctionToPointerDecay
136 expression: DeclRef - tmpl
137 template argument: Type
138 type: Builtin - unsigned int
139 statement: Return
140 expression: DependentScopeDeclRef - value
141 specifier: TypeSpec
142 type: TemplateTypeParm - T
143 )"},
144 {R"cpp(
145struct Foo { char operator+(int); };
146char root = Foo() + 42;
147 )cpp",
148 R"(
149declaration: Var - root
150 type: Builtin - char
151 expression: ExprWithCleanups
152 expression: CXXOperatorCall
153 expression: ImplicitCast - FunctionToPointerDecay
154 expression: DeclRef - operator+
155 expression: MaterializeTemporary - lvalue
156 expression: CXXTemporaryObject - Foo
157 type: Elaborated
158 type: Record - Foo
159 expression: IntegerLiteral - 42
160 )"},
161 {R"cpp(
162struct Bar {
163 int x;
164 int root() const {
165 return x;
166 }
167};
168 )cpp",
169 R"(
170declaration: CXXMethod - root
171 type: FunctionProto
172 type: Builtin - int
173 statement: Compound
174 statement: Return
175 expression: ImplicitCast - LValueToRValue
176 expression: Member - x
177 expression: CXXThis - const, implicit
178 )"},
179 };
180 for (const auto &Case : Cases) {
181 ParsedAST AST = TestTU::withCode(Case.first).build();
182 auto Node = dumpAST(DynTypedNode::create(findUnqualifiedDecl(AST, "root")),
183 AST.getTokens(), AST.getASTContext());
184 EXPECT_EQ(llvm::StringRef(Case.second).trim(),
185 llvm::StringRef(llvm::to_string(Node)).trim());
186 }
187}
188
189TEST(DumpASTTests, Range) {
190 Annotations Case("$var[[$type[[int]] x]];");
191 ParsedAST AST = TestTU::withCode(Case.code()).build();
192 auto Node = dumpAST(DynTypedNode::create(findDecl(AST, "x")), AST.getTokens(),
193 AST.getASTContext());
194 EXPECT_EQ(Node.range, Case.range("var"));
195 ASSERT_THAT(Node.children, SizeIs(1)) << "Expected one child typeloc";
196 EXPECT_EQ(Node.children.front().range, Case.range("type"));
197}
198
199TEST(DumpASTTests, NoRange) {
200 auto TU = TestTU::withHeaderCode("void funcFromHeader();");
201 TU.Code = "int varFromSource;";
202 ParsedAST AST = TU.build();
203 auto Node = dumpAST(
204 DynTypedNode::create(*AST.getASTContext().getTranslationUnitDecl()),
205 AST.getTokens(), AST.getASTContext());
206 ASSERT_THAT(Node.children, Contains(withDetail("varFromSource")));
207 ASSERT_THAT(Node.children, Not(Contains(withDetail("funcFromHeader"))));
208 EXPECT_THAT(Node.arcana, testing::StartsWith("TranslationUnitDecl "));
209 ASSERT_FALSE(Node.range) << "Expected no range for translation unit";
210}
211
212TEST(DumpASTTests, Arcana) {
213 ParsedAST AST = TestTU::withCode("int x;").build();
214 auto Node = dumpAST(DynTypedNode::create(findDecl(AST, "x")), AST.getTokens(),
215 AST.getASTContext());
216 EXPECT_THAT(Node.arcana, testing::StartsWith("VarDecl "));
217 EXPECT_THAT(Node.arcana, testing::EndsWith(" 'int'"));
218 ASSERT_THAT(Node.children, SizeIs(1)) << "Expected one child typeloc";
219 EXPECT_THAT(Node.children.front().arcana, testing::StartsWith("QualType "));
220}
221
222TEST(DumpASTTests, UnbalancedBraces) {
223 // Test that we don't crash while trying to compute a source range for the
224 // node whose ending brace is missing, and also that the source range is
225 // not empty.
226 Annotations Case("/*error-ok*/ $func[[int main() {]]");
227 ParsedAST AST = TestTU::withCode(Case.code()).build();
228 auto Node = dumpAST(DynTypedNode::create(findDecl(AST, "main")),
229 AST.getTokens(), AST.getASTContext());
230 ASSERT_EQ(Node.range, Case.range("func"));
231}
232
233} // namespace
234} // namespace clangd
235} // namespace clang
::clang::DynTypedNode Node
const NamedDecl & findDecl(ParsedAST &AST, llvm::StringRef QName)
Definition: TestTU.cpp:219
ASTNode dumpAST(const DynTypedNode &N, const syntax::TokenBuffer &Tokens, const ASTContext &Ctx)
Definition: DumpAST.cpp:416
MATCHER_P(named, N, "")
TEST(BackgroundQueueTest, Priority)
const NamedDecl & findUnqualifiedDecl(ParsedAST &AST, llvm::StringRef Name)
Definition: TestTU.cpp:260
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
ParsedAST build() const
Definition: TestTU.cpp:114
static TestTU withHeaderCode(llvm::StringRef HeaderCode)
Definition: TestTU.h:42
static TestTU withCode(llvm::StringRef Code)
Definition: TestTU.h:36