1//===- unittest/AST/ASTTypeTraits.cpp - AST type traits unit tests ------===//
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
10#include "clang/AST/ASTTypeTraits.h"
11#include "MatchVerifier.h"
12#include "gtest/gtest.h"
13
14using namespace clang::ast_matchers;
15
16namespace clang {
17namespace {
18
19TEST(ASTNodeKind, NoKind) {
20 EXPECT_FALSE(ASTNodeKind().isBaseOf(ASTNodeKind()));
21 EXPECT_FALSE(ASTNodeKind().isSame(ASTNodeKind()));
22}
23
24template <typename T> static ASTNodeKind DNT() {
25 return ASTNodeKind::getFromNodeKind<T>();
26}
27
28TEST(ASTNodeKind, IsNone) {
29 EXPECT_TRUE(ASTNodeKind().isNone());
30 EXPECT_FALSE(DNT<Decl>().isNone());
31 EXPECT_FALSE(DNT<VarDecl>().isNone());
32}
33
34TEST(ASTNodeKind, Bases) {
35 EXPECT_TRUE(DNT<Decl>().isBaseOf(DNT<VarDecl>()));
36 EXPECT_FALSE(DNT<Decl>().isSame(DNT<VarDecl>()));
37 EXPECT_FALSE(DNT<VarDecl>().isBaseOf(DNT<Decl>()));
38
39 EXPECT_TRUE(DNT<Decl>().isSame(DNT<Decl>()));
40}
41
42TEST(DynTypedNode, Clades) {
43 EXPECT_TRUE(DNT<Stmt>().getCladeKind().isSame(DNT<Stmt>()));
44 EXPECT_TRUE(DNT<Decl>().getCladeKind().isSame(DNT<Decl>()));
45
46 EXPECT_TRUE(DNT<CXXMethodDecl>().getCladeKind().isSame(DNT<Decl>()));
47 EXPECT_TRUE(DNT<CXXMemberCallExpr>().getCladeKind().isSame(DNT<Stmt>()));
48
49 EXPECT_FALSE(DNT<CXXMemberCallExpr>().getCladeKind().isSame(DNT<Decl>()));
50
51 EXPECT_TRUE(ASTNodeKind().getCladeKind().isNone());
52}
53
54TEST(ASTNodeKind, BaseDistances) {
55 unsigned Distance = 1;
56 EXPECT_TRUE(DNT<Expr>().isBaseOf(DNT<Expr>(), &Distance));
57 EXPECT_EQ(0u, Distance);
58
59 EXPECT_TRUE(DNT<Stmt>().isBaseOf(DNT<IfStmt>(), &Distance));
60 EXPECT_EQ(1u, Distance);
61
62 Distance = 3;
63 EXPECT_TRUE(DNT<DeclaratorDecl>().isBaseOf(DNT<ParmVarDecl>(), &Distance));
64 EXPECT_EQ(2u, Distance);
65}
66
67TEST(ASTNodeKind, SameBase) {
68 EXPECT_TRUE(DNT<Expr>().isBaseOf(DNT<CallExpr>()));
69 EXPECT_TRUE(DNT<Expr>().isBaseOf(DNT<BinaryOperator>()));
70 EXPECT_FALSE(DNT<CallExpr>().isBaseOf(DNT<BinaryOperator>()));
71 EXPECT_FALSE(DNT<BinaryOperator>().isBaseOf(DNT<CallExpr>()));
72}
73
74TEST(ASTNodeKind, DiffBase) {
75 EXPECT_FALSE(DNT<Expr>().isBaseOf(DNT<ArrayType>()));
76 EXPECT_FALSE(DNT<QualType>().isBaseOf(DNT<FunctionDecl>()));
77 EXPECT_FALSE(DNT<Type>().isSame(DNT<QualType>()));
78}
79
80TEST(ASTNodeKind, MostDerivedType) {
81 EXPECT_TRUE(DNT<BinaryOperator>().isSame(
82 ASTNodeKind::getMostDerivedType(DNT<Expr>(), DNT<BinaryOperator>())));
83 EXPECT_TRUE(DNT<BinaryOperator>().isSame(
84 ASTNodeKind::getMostDerivedType(DNT<BinaryOperator>(), DNT<Expr>())));
85 EXPECT_TRUE(DNT<VarDecl>().isSame(
86 ASTNodeKind::getMostDerivedType(DNT<VarDecl>(), DNT<VarDecl>())));
87
88 // Not related. Returns nothing.
89 EXPECT_TRUE(
90 ASTNodeKind::getMostDerivedType(DNT<IfStmt>(), DNT<VarDecl>()).isNone());
91 EXPECT_TRUE(ASTNodeKind::getMostDerivedType(DNT<IfStmt>(),
92 DNT<BinaryOperator>()).isNone());
93}
94
95TEST(ASTNodeKind, MostDerivedCommonAncestor) {
96 EXPECT_TRUE(DNT<Expr>().isSame(ASTNodeKind::getMostDerivedCommonAncestor(
97 DNT<Expr>(), DNT<BinaryOperator>())));
98 EXPECT_TRUE(DNT<Expr>().isSame(ASTNodeKind::getMostDerivedCommonAncestor(
99 DNT<BinaryOperator>(), DNT<Expr>())));
100 EXPECT_TRUE(DNT<VarDecl>().isSame(ASTNodeKind::getMostDerivedCommonAncestor(
101 DNT<VarDecl>(), DNT<VarDecl>())));
102
103 // A little related. Returns the ancestor.
104 EXPECT_TRUE(
105 DNT<NamedDecl>().isSame(ASTNodeKind::getMostDerivedCommonAncestor(
106 DNT<CXXMethodDecl>(), DNT<RecordDecl>())));
107
108 // Not related. Returns nothing.
109 EXPECT_TRUE(ASTNodeKind::getMostDerivedCommonAncestor(
110 DNT<IfStmt>(), DNT<VarDecl>()).isNone());
111}
112
113struct Foo {};
114
115TEST(ASTNodeKind, UnknownKind) {
116 // We can construct one, but it is nowhere in the hierarchy.
117 EXPECT_FALSE(DNT<Foo>().isSame(DNT<Foo>()));
118}
119
120template <typename T>
121constexpr bool HasPointerIdentity =
122 ASTNodeKind::getFromNodeKind<T>().hasPointerIdentity();
123
124TEST(ASTNodeKind, ConstexprHasPointerIdentity) {
125 EXPECT_TRUE(HasPointerIdentity<Decl>);
126 EXPECT_TRUE(HasPointerIdentity<Stmt>);
127 EXPECT_FALSE(HasPointerIdentity<TypeLoc>);
128 EXPECT_FALSE(HasPointerIdentity<QualType>);
129 EXPECT_FALSE(HasPointerIdentity<Foo>);
130
131 constexpr bool DefaultConstructedHasPointerIdentity =
132 ASTNodeKind().hasPointerIdentity();
133 EXPECT_FALSE(DefaultConstructedHasPointerIdentity);
134}
135
136template <typename T, typename U>
137constexpr bool NodeKindIsSame =
138 ASTNodeKind::getFromNodeKind<T>().isSame(ASTNodeKind::getFromNodeKind<U>());
139
140TEST(ASTNodeKind, ConstexprIsSame) {
141 EXPECT_TRUE((NodeKindIsSame<Decl, Decl>));
142 EXPECT_FALSE((NodeKindIsSame<Decl, VarDecl>));
143 EXPECT_FALSE((NodeKindIsSame<Foo, Foo>));
144
145 constexpr bool DefaultConstructedIsSameToDefaultConstructed =
146 ASTNodeKind().isSame(Other: ASTNodeKind());
147 EXPECT_FALSE(DefaultConstructedIsSameToDefaultConstructed);
148}
149
150template <typename T>
151constexpr bool NodeKindIsNone = ASTNodeKind::getFromNodeKind<T>().isNone();
152
153TEST(ASTNodeKind, ConstexprIsNone) {
154 EXPECT_FALSE(NodeKindIsNone<Decl>);
155 EXPECT_TRUE(NodeKindIsNone<Foo>);
156
157 constexpr bool DefaultConstructedIsNone = ASTNodeKind().isNone();
158 EXPECT_TRUE(DefaultConstructedIsNone);
159}
160
161TEST(ASTNodeKind, Name) {
162 EXPECT_EQ("<None>", ASTNodeKind().asStringRef());
163#define VERIFY_NAME(Node) EXPECT_EQ(#Node, DNT<Node>().asStringRef());
164 VERIFY_NAME(TemplateArgument);
165 VERIFY_NAME(NestedNameSpecifierLoc);
166 VERIFY_NAME(QualType);
167 VERIFY_NAME(TypeLoc);
168 VERIFY_NAME(CXXCtorInitializer);
169 VERIFY_NAME(ConceptReference);
170 VERIFY_NAME(NestedNameSpecifier);
171 VERIFY_NAME(Decl);
172 VERIFY_NAME(CXXRecordDecl);
173 VERIFY_NAME(Stmt);
174 VERIFY_NAME(CallExpr);
175 VERIFY_NAME(Type);
176 VERIFY_NAME(ConstantArrayType);
177 VERIFY_NAME(NonNullAttr);
178#undef VERIFY_NAME
179}
180
181TEST(DynTypedNode, DeclSourceRange) {
182 RangeVerifier<DynTypedNode> Verifier;
183 Verifier.expectRange(BeginLine: 1, BeginColumn: 1, EndLine: 1, EndColumn: 11);
184 EXPECT_TRUE(Verifier.match("void f() {}", decl()));
185}
186
187TEST(DynTypedNode, StmtSourceRange) {
188 RangeVerifier<DynTypedNode> Verifier;
189 Verifier.expectRange(BeginLine: 1, BeginColumn: 10, EndLine: 1, EndColumn: 11);
190 EXPECT_TRUE(Verifier.match("void f() {}", stmt()));
191}
192
193TEST(DynTypedNode, TypeLocSourceRange) {
194 RangeVerifier<DynTypedNode> Verifier;
195 Verifier.expectRange(BeginLine: 1, BeginColumn: 1, EndLine: 1, EndColumn: 8);
196 EXPECT_TRUE(Verifier.match("void f() {}", typeLoc(loc(functionType()))));
197}
198
199TEST(DynTypedNode, NNSLocSourceRange) {
200 RangeVerifier<DynTypedNode> Verifier;
201 Verifier.expectRange(BeginLine: 1, BeginColumn: 33, EndLine: 1, EndColumn: 34);
202 EXPECT_TRUE(Verifier.match("namespace N { typedef void T; } N::T f() {}",
203 nestedNameSpecifierLoc()));
204}
205
206TEST(DynTypedNode, AttrSourceRange) {
207 RangeVerifier<DynTypedNode> Verifier;
208 Verifier.expectRange(BeginLine: 1, BeginColumn: 31, EndLine: 1, EndColumn: 31);
209 EXPECT_TRUE(Verifier.match("void x(char *y __attribute__((nonnull)) );",
210 ast_matchers::attr()));
211}
212
213// FIXME: add tests for ConceptReference once we add an ASTMatcher.
214
215TEST(DynTypedNode, DeclDump) {
216 DumpVerifier Verifier;
217 Verifier.expectSubstring(Str: "FunctionDecl");
218 EXPECT_TRUE(Verifier.match("void f() {}", functionDecl()));
219}
220
221TEST(DynTypedNode, StmtDump) {
222 DumpVerifier Verifier;
223 Verifier.expectSubstring(Str: "CompoundStmt");
224 EXPECT_TRUE(Verifier.match("void f() {}", stmt()));
225}
226
227TEST(DynTypedNode, DeclPrint) {
228 PrintVerifier Verifier;
229 Verifier.expectString(Str: "void f() {\n}\n");
230 EXPECT_TRUE(Verifier.match("void f() {}", functionDecl()));
231}
232
233TEST(DynTypedNode, StmtPrint) {
234 PrintVerifier Verifier;
235 Verifier.expectString(Str: "{\n}\n");
236 EXPECT_TRUE(Verifier.match("void f() {}", stmt()));
237}
238
239TEST(DynTypedNode, QualType) {
240 QualType Q;
241 DynTypedNode Node = DynTypedNode::create(Node: Q);
242 EXPECT_TRUE(Node == Node);
243 EXPECT_FALSE(Node < Node);
244}
245
246TEST(DynTypedNode, TypeLoc) {
247 std::string code = R"cc(void example() { int abc; })cc";
248 auto AST = clang::tooling::buildASTFromCode(Code: code);
249 auto matches =
250 match(Matcher: traverse(TK: TK_AsIs,
251 InnerMatcher: varDecl(hasName(Name: "abc"), hasTypeLoc(Inner: typeLoc().bind(ID: "tl")))),
252 Context&: AST->getASTContext());
253 EXPECT_EQ(matches.size(), 1u);
254
255 const auto &tl = *matches[0].getNodeAs<TypeLoc>(ID: "tl");
256 DynTypedNode Node = DynTypedNode::create(Node: tl);
257 EXPECT_TRUE(Node == Node);
258 EXPECT_FALSE(Node < Node);
259}
260
261TEST(DynTypedNode, PointerTypeLoc) {
262 std::string code = R"cc(void example() { int *abc; })cc";
263 auto AST = clang::tooling::buildASTFromCode(Code: code);
264 auto matches =
265 match(Matcher: traverse(TK: TK_AsIs, InnerMatcher: varDecl(hasName(Name: "abc"),
266 hasTypeLoc(Inner: typeLoc().bind(ID: "ptl")))),
267 Context&: AST->getASTContext());
268 EXPECT_EQ(matches.size(), 1u);
269
270 const auto &tl = *matches[0].getNodeAs<TypeLoc>(ID: "ptl");
271 DynTypedNode TypeLocNode = DynTypedNode::create(Node: tl);
272 EXPECT_TRUE(TypeLocNode == TypeLocNode);
273 EXPECT_FALSE(TypeLocNode < TypeLocNode);
274
275 const auto &ptl = *matches[0].getNodeAs<PointerTypeLoc>(ID: "ptl");
276 EXPECT_EQ(&tl, &ptl);
277 DynTypedNode PointerTypeLocNode = DynTypedNode::create(Node: ptl);
278 EXPECT_TRUE(PointerTypeLocNode == PointerTypeLocNode);
279 EXPECT_FALSE(PointerTypeLocNode < PointerTypeLocNode);
280}
281
282} // namespace
283} // namespace clang
284

source code of clang/unittests/AST/ASTTypeTraitsTest.cpp