#include "clang/AST/ASTTypeTraits.h"
#include "MatchVerifier.h"
#include "gtest/gtest.h"
using namespace clang::ast_matchers;
namespace clang {
namespace {
TEST(ASTNodeKind, NoKind) {
EXPECT_FALSE(ASTNodeKind().isBaseOf(ASTNodeKind()));
EXPECT_FALSE(ASTNodeKind().isSame(ASTNodeKind()));
}
template <typename T> static ASTNodeKind DNT() {
return ASTNodeKind::getFromNodeKind<T>();
}
TEST(ASTNodeKind, IsNone) {
EXPECT_TRUE(ASTNodeKind().isNone());
EXPECT_FALSE(DNT<Decl>().isNone());
EXPECT_FALSE(DNT<VarDecl>().isNone());
}
TEST(ASTNodeKind, Bases) {
EXPECT_TRUE(DNT<Decl>().isBaseOf(DNT<VarDecl>()));
EXPECT_FALSE(DNT<Decl>().isSame(DNT<VarDecl>()));
EXPECT_FALSE(DNT<VarDecl>().isBaseOf(DNT<Decl>()));
EXPECT_TRUE(DNT<Decl>().isSame(DNT<Decl>()));
}
TEST(DynTypedNode, Clades) {
EXPECT_TRUE(DNT<Stmt>().getCladeKind().isSame(DNT<Stmt>()));
EXPECT_TRUE(DNT<Decl>().getCladeKind().isSame(DNT<Decl>()));
EXPECT_TRUE(DNT<CXXMethodDecl>().getCladeKind().isSame(DNT<Decl>()));
EXPECT_TRUE(DNT<CXXMemberCallExpr>().getCladeKind().isSame(DNT<Stmt>()));
EXPECT_FALSE(DNT<CXXMemberCallExpr>().getCladeKind().isSame(DNT<Decl>()));
EXPECT_TRUE(ASTNodeKind().getCladeKind().isNone());
}
TEST(ASTNodeKind, BaseDistances) {
unsigned Distance = 1;
EXPECT_TRUE(DNT<Expr>().isBaseOf(DNT<Expr>(), &Distance));
EXPECT_EQ(0u, Distance);
EXPECT_TRUE(DNT<Stmt>().isBaseOf(DNT<IfStmt>(), &Distance));
EXPECT_EQ(1u, Distance);
Distance = 3;
EXPECT_TRUE(DNT<DeclaratorDecl>().isBaseOf(DNT<ParmVarDecl>(), &Distance));
EXPECT_EQ(2u, Distance);
}
TEST(ASTNodeKind, SameBase) {
EXPECT_TRUE(DNT<Expr>().isBaseOf(DNT<CallExpr>()));
EXPECT_TRUE(DNT<Expr>().isBaseOf(DNT<BinaryOperator>()));
EXPECT_FALSE(DNT<CallExpr>().isBaseOf(DNT<BinaryOperator>()));
EXPECT_FALSE(DNT<BinaryOperator>().isBaseOf(DNT<CallExpr>()));
}
TEST(ASTNodeKind, DiffBase) {
EXPECT_FALSE(DNT<Expr>().isBaseOf(DNT<ArrayType>()));
EXPECT_FALSE(DNT<QualType>().isBaseOf(DNT<FunctionDecl>()));
EXPECT_FALSE(DNT<Type>().isSame(DNT<QualType>()));
}
TEST(ASTNodeKind, MostDerivedType) {
EXPECT_TRUE(DNT<BinaryOperator>().isSame(
ASTNodeKind::getMostDerivedType(DNT<Expr>(), DNT<BinaryOperator>())));
EXPECT_TRUE(DNT<BinaryOperator>().isSame(
ASTNodeKind::getMostDerivedType(DNT<BinaryOperator>(), DNT<Expr>())));
EXPECT_TRUE(DNT<VarDecl>().isSame(
ASTNodeKind::getMostDerivedType(DNT<VarDecl>(), DNT<VarDecl>())));
EXPECT_TRUE(
ASTNodeKind::getMostDerivedType(DNT<IfStmt>(), DNT<VarDecl>()).isNone());
EXPECT_TRUE(ASTNodeKind::getMostDerivedType(DNT<IfStmt>(),
DNT<BinaryOperator>()).isNone());
}
TEST(ASTNodeKind, MostDerivedCommonAncestor) {
EXPECT_TRUE(DNT<Expr>().isSame(ASTNodeKind::getMostDerivedCommonAncestor(
DNT<Expr>(), DNT<BinaryOperator>())));
EXPECT_TRUE(DNT<Expr>().isSame(ASTNodeKind::getMostDerivedCommonAncestor(
DNT<BinaryOperator>(), DNT<Expr>())));
EXPECT_TRUE(DNT<VarDecl>().isSame(ASTNodeKind::getMostDerivedCommonAncestor(
DNT<VarDecl>(), DNT<VarDecl>())));
EXPECT_TRUE(
DNT<NamedDecl>().isSame(ASTNodeKind::getMostDerivedCommonAncestor(
DNT<CXXMethodDecl>(), DNT<RecordDecl>())));
EXPECT_TRUE(ASTNodeKind::getMostDerivedCommonAncestor(
DNT<IfStmt>(), DNT<VarDecl>()).isNone());
}
struct Foo {};
TEST(ASTNodeKind, UnknownKind) {
EXPECT_FALSE(DNT<Foo>().isSame(DNT<Foo>()));
}
TEST(ASTNodeKind, Name) {
EXPECT_EQ("<None>", ASTNodeKind().asStringRef());
#define VERIFY_NAME(Node) EXPECT_EQ(#Node, DNT<Node>().asStringRef());
VERIFY_NAME(TemplateArgument);
VERIFY_NAME(NestedNameSpecifierLoc);
VERIFY_NAME(QualType);
VERIFY_NAME(TypeLoc);
VERIFY_NAME(CXXCtorInitializer);
VERIFY_NAME(NestedNameSpecifier);
VERIFY_NAME(Decl);
VERIFY_NAME(CXXRecordDecl);
VERIFY_NAME(Stmt);
VERIFY_NAME(CallExpr);
VERIFY_NAME(Type);
VERIFY_NAME(ConstantArrayType);
VERIFY_NAME(NonNullAttr);
#undef VERIFY_NAME
}
TEST(DynTypedNode, DeclSourceRange) {
RangeVerifier<DynTypedNode> Verifier;
Verifier.expectRange(1, 1, 1, 11);
EXPECT_TRUE(Verifier.match("void f() {}", decl()));
}
TEST(DynTypedNode, StmtSourceRange) {
RangeVerifier<DynTypedNode> Verifier;
Verifier.expectRange(1, 10, 1, 11);
EXPECT_TRUE(Verifier.match("void f() {}", stmt()));
}
TEST(DynTypedNode, TypeLocSourceRange) {
RangeVerifier<DynTypedNode> Verifier;
Verifier.expectRange(1, 1, 1, 8);
EXPECT_TRUE(Verifier.match("void f() {}", typeLoc(loc(functionType()))));
}
TEST(DynTypedNode, NNSLocSourceRange) {
RangeVerifier<DynTypedNode> Verifier;
Verifier.expectRange(1, 33, 1, 34);
EXPECT_TRUE(Verifier.match("namespace N { typedef void T; } N::T f() {}",
nestedNameSpecifierLoc()));
}
TEST(DynTypedNode, AttrSourceRange) {
RangeVerifier<DynTypedNode> Verifier;
Verifier.expectRange(1, 31, 1, 31);
EXPECT_TRUE(Verifier.match("void x(char *y __attribute__((nonnull)) );",
ast_matchers::attr()));
}
TEST(DynTypedNode, DeclDump) {
DumpVerifier Verifier;
Verifier.expectSubstring("FunctionDecl");
EXPECT_TRUE(Verifier.match("void f() {}", functionDecl()));
}
TEST(DynTypedNode, StmtDump) {
DumpVerifier Verifier;
Verifier.expectSubstring("CompoundStmt");
EXPECT_TRUE(Verifier.match("void f() {}", stmt()));
}
TEST(DynTypedNode, DeclPrint) {
PrintVerifier Verifier;
Verifier.expectString("void f() {\n}\n");
EXPECT_TRUE(Verifier.match("void f() {}", functionDecl()));
}
TEST(DynTypedNode, StmtPrint) {
PrintVerifier Verifier;
Verifier.expectString("{\n}\n");
EXPECT_TRUE(Verifier.match("void f() {}", stmt()));
}
TEST(DynTypedNode, QualType) {
QualType Q;
DynTypedNode Node = DynTypedNode::create(Q);
EXPECT_TRUE(Node == Node);
EXPECT_FALSE(Node < Node);
}
TEST(DynTypedNode, TypeLoc) {
std::string code = R"cc(void example() { int abc; })cc";
auto AST = clang::tooling::buildASTFromCode(code);
auto matches =
match(traverse(TK_AsIs,
varDecl(hasName("abc"), hasTypeLoc(typeLoc().bind("tl")))),
AST->getASTContext());
EXPECT_EQ(matches.size(), 1u);
const auto &tl = *matches[0].getNodeAs<TypeLoc>("tl");
DynTypedNode Node = DynTypedNode::create(tl);
EXPECT_TRUE(Node == Node);
EXPECT_FALSE(Node < Node);
}
TEST(DynTypedNode, PointerTypeLoc) {
std::string code = R"cc(void example() { int *abc; })cc";
auto AST = clang::tooling::buildASTFromCode(code);
auto matches =
match(traverse(TK_AsIs, varDecl(hasName("abc"),
hasTypeLoc(typeLoc().bind("ptl")))),
AST->getASTContext());
EXPECT_EQ(matches.size(), 1u);
const auto &tl = *matches[0].getNodeAs<TypeLoc>("ptl");
DynTypedNode TypeLocNode = DynTypedNode::create(tl);
EXPECT_TRUE(TypeLocNode == TypeLocNode);
EXPECT_FALSE(TypeLocNode < TypeLocNode);
const auto &ptl = *matches[0].getNodeAs<PointerTypeLoc>("ptl");
EXPECT_EQ(&tl, &ptl);
DynTypedNode PointerTypeLocNode = DynTypedNode::create(ptl);
EXPECT_TRUE(PointerTypeLocNode == PointerTypeLocNode);
EXPECT_FALSE(PointerTypeLocNode < PointerTypeLocNode);
}
} }