284 lines · cpp
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-exception6//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(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_NAME179}180 181TEST(DynTypedNode, DeclSourceRange) {182 RangeVerifier<DynTypedNode> Verifier;183 Verifier.expectRange(1, 1, 1, 11);184 EXPECT_TRUE(Verifier.match("void f() {}", decl()));185}186 187TEST(DynTypedNode, StmtSourceRange) {188 RangeVerifier<DynTypedNode> Verifier;189 Verifier.expectRange(1, 10, 1, 11);190 EXPECT_TRUE(Verifier.match("void f() {}", stmt()));191}192 193TEST(DynTypedNode, TypeLocSourceRange) {194 RangeVerifier<DynTypedNode> Verifier;195 Verifier.expectRange(1, 1, 1, 8);196 EXPECT_TRUE(Verifier.match("void f() {}", typeLoc(loc(functionType()))));197}198 199TEST(DynTypedNode, NNSLocSourceRange) {200 RangeVerifier<DynTypedNode> Verifier;201 Verifier.expectRange(1, 33, 1, 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(1, 31, 1, 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("FunctionDecl");218 EXPECT_TRUE(Verifier.match("void f() {}", functionDecl()));219}220 221TEST(DynTypedNode, StmtDump) {222 DumpVerifier Verifier;223 Verifier.expectSubstring("CompoundStmt");224 EXPECT_TRUE(Verifier.match("void f() {}", stmt()));225}226 227TEST(DynTypedNode, DeclPrint) {228 PrintVerifier Verifier;229 Verifier.expectString("void f() {\n}\n");230 EXPECT_TRUE(Verifier.match("void f() {}", functionDecl()));231}232 233TEST(DynTypedNode, StmtPrint) {234 PrintVerifier Verifier;235 Verifier.expectString("{\n}\n");236 EXPECT_TRUE(Verifier.match("void f() {}", stmt()));237}238 239TEST(DynTypedNode, QualType) {240 QualType Q;241 DynTypedNode Node = DynTypedNode::create(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);249 auto matches =250 match(traverse(TK_AsIs,251 varDecl(hasName("abc"), hasTypeLoc(typeLoc().bind("tl")))),252 AST->getASTContext());253 EXPECT_EQ(matches.size(), 1u);254 255 const auto &tl = *matches[0].getNodeAs<TypeLoc>("tl");256 DynTypedNode Node = DynTypedNode::create(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);264 auto matches =265 match(traverse(TK_AsIs, varDecl(hasName("abc"),266 hasTypeLoc(typeLoc().bind("ptl")))),267 AST->getASTContext());268 EXPECT_EQ(matches.size(), 1u);269 270 const auto &tl = *matches[0].getNodeAs<TypeLoc>("ptl");271 DynTypedNode TypeLocNode = DynTypedNode::create(tl);272 EXPECT_TRUE(TypeLocNode == TypeLocNode);273 EXPECT_FALSE(TypeLocNode < TypeLocNode);274 275 const auto &ptl = *matches[0].getNodeAs<PointerTypeLoc>("ptl");276 EXPECT_EQ(&tl, &ptl);277 DynTypedNode PointerTypeLocNode = DynTypedNode::create(ptl);278 EXPECT_TRUE(PointerTypeLocNode == PointerTypeLocNode);279 EXPECT_FALSE(PointerTypeLocNode < PointerTypeLocNode);280}281 282} // namespace283} // namespace clang284