summaryrefslogtreecommitdiffstats
path: root/clang/unittests
diff options
context:
space:
mode:
authorBalazs Keri <1.int32@gmail.com>2019-09-02 11:01:09 +0000
committerBalazs Keri <1.int32@gmail.com>2019-09-02 11:01:09 +0000
commitb06b14ba8cf32c16119bea9252468dea58a61200 (patch)
tree546ecf7b9a7c050eab5fc66da8d4b357fbcfbeb3 /clang/unittests
parent1aab62762f6658a6955d9bed719a345702f2bb56 (diff)
downloadbcm5719-llvm-b06b14ba8cf32c16119bea9252468dea58a61200.tar.gz
bcm5719-llvm-b06b14ba8cf32c16119bea9252468dea58a61200.zip
[AST] AST structural equivalence to work internally with pairs.
Summary: The structural equivalence check stores now pairs of nodes in the 'from' and 'to' context instead of only the node in 'from' context and a corresponding one in 'to' context. This is needed to handle cases when a Decl in the 'from' context is to be compared with multiple Decls in the 'to' context. Reviewers: martong, a_sidorin Reviewed By: martong, a_sidorin Subscribers: rnkovacs, dkrupp, Szelethus, gamesh411, cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D66538 llvm-svn: 370639
Diffstat (limited to 'clang/unittests')
-rw-r--r--clang/unittests/AST/StructuralEquivalenceTest.cpp122
1 files changed, 122 insertions, 0 deletions
diff --git a/clang/unittests/AST/StructuralEquivalenceTest.cpp b/clang/unittests/AST/StructuralEquivalenceTest.cpp
index c413576a8a7..8e467527ead 100644
--- a/clang/unittests/AST/StructuralEquivalenceTest.cpp
+++ b/clang/unittests/AST/StructuralEquivalenceTest.cpp
@@ -1273,6 +1273,128 @@ TEST_F(
classTemplateSpecializationDecl(hasName("Primary")));
EXPECT_FALSE(testStructuralMatch(t));
}
+struct StructuralEquivalenceCacheTest : public StructuralEquivalenceTest {
+ llvm::DenseSet<std::pair<Decl *, Decl *>> NonEquivalentDecls;
+
+ template <typename NodeType, typename MatcherType>
+ std::pair<NodeType *, NodeType *>
+ findDeclPair(std::tuple<TranslationUnitDecl *, TranslationUnitDecl *> TU,
+ MatcherType M) {
+ NodeType *D0 = FirstDeclMatcher<NodeType>().match(get<0>(TU), M);
+ NodeType *D1 = FirstDeclMatcher<NodeType>().match(get<1>(TU), M);
+ return {D0, D1};
+ }
+
+ template <typename NodeType>
+ bool isInNonEqCache(std::pair<NodeType *, NodeType *> D) {
+ return NonEquivalentDecls.count(D) > 0;
+ }
+};
+
+TEST_F(StructuralEquivalenceCacheTest, SimpleNonEq) {
+ auto TU = makeTuDecls(
+ R"(
+ class A {};
+ class B {};
+ void x(A, A);
+ )",
+ R"(
+ class A {};
+ class B {};
+ void x(A, B);
+ )",
+ Lang_CXX);
+
+ StructuralEquivalenceContext Ctx(
+ get<0>(TU)->getASTContext(), get<1>(TU)->getASTContext(),
+ NonEquivalentDecls, StructuralEquivalenceKind::Default, false, false);
+
+ auto X = findDeclPair<FunctionDecl>(TU, functionDecl(hasName("x")));
+ EXPECT_FALSE(Ctx.IsEquivalent(X.first, X.second));
+
+ EXPECT_FALSE(isInNonEqCache(findDeclPair<CXXRecordDecl>(
+ TU, cxxRecordDecl(hasName("A"), unless(isImplicit())))));
+ EXPECT_FALSE(isInNonEqCache(findDeclPair<CXXRecordDecl>(
+ TU, cxxRecordDecl(hasName("B"), unless(isImplicit())))));
+}
+
+TEST_F(StructuralEquivalenceCacheTest, SpecialNonEq) {
+ auto TU = makeTuDecls(
+ R"(
+ class A {};
+ class B { int i; };
+ void x(A *);
+ void y(A *);
+ class C {
+ friend void x(A *);
+ friend void y(A *);
+ };
+ )",
+ R"(
+ class A {};
+ class B { int i; };
+ void x(A *);
+ void y(B *);
+ class C {
+ friend void x(A *);
+ friend void y(B *);
+ };
+ )",
+ Lang_CXX);
+
+ StructuralEquivalenceContext Ctx(
+ get<0>(TU)->getASTContext(), get<1>(TU)->getASTContext(),
+ NonEquivalentDecls, StructuralEquivalenceKind::Default, false, false);
+
+ auto C = findDeclPair<CXXRecordDecl>(
+ TU, cxxRecordDecl(hasName("C"), unless(isImplicit())));
+ EXPECT_FALSE(Ctx.IsEquivalent(C.first, C.second));
+
+ EXPECT_FALSE(isInNonEqCache(C));
+ EXPECT_FALSE(isInNonEqCache(findDeclPair<CXXRecordDecl>(
+ TU, cxxRecordDecl(hasName("A"), unless(isImplicit())))));
+ EXPECT_FALSE(isInNonEqCache(findDeclPair<CXXRecordDecl>(
+ TU, cxxRecordDecl(hasName("B"), unless(isImplicit())))));
+ EXPECT_FALSE(isInNonEqCache(
+ findDeclPair<FunctionDecl>(TU, functionDecl(hasName("x")))));
+ EXPECT_FALSE(isInNonEqCache(
+ findDeclPair<FunctionDecl>(TU, functionDecl(hasName("y")))));
+}
+
+TEST_F(StructuralEquivalenceCacheTest, Cycle) {
+ auto TU = makeTuDecls(
+ R"(
+ class C;
+ class A { C *c; };
+ void x(A *);
+ class C {
+ friend void x(A *);
+ };
+ )",
+ R"(
+ class C;
+ class A { C *c; };
+ void x(A *);
+ class C {
+ friend void x(A *);
+ };
+ )",
+ Lang_CXX);
+
+ StructuralEquivalenceContext Ctx(
+ get<0>(TU)->getASTContext(), get<1>(TU)->getASTContext(),
+ NonEquivalentDecls, StructuralEquivalenceKind::Default, false, false);
+
+ auto C = findDeclPair<CXXRecordDecl>(
+ TU, cxxRecordDecl(hasName("C"), unless(isImplicit())));
+ EXPECT_TRUE(Ctx.IsEquivalent(C.first, C.second));
+
+ EXPECT_FALSE(isInNonEqCache(C));
+ EXPECT_FALSE(isInNonEqCache(findDeclPair<CXXRecordDecl>(
+ TU, cxxRecordDecl(hasName("A"), unless(isImplicit())))));
+ EXPECT_FALSE(isInNonEqCache(
+ findDeclPair<FunctionDecl>(TU, functionDecl(hasName("x")))));
+}
} // end namespace ast_matchers
} // end namespace clang
OpenPOWER on IntegriCloud