diff options
| author | Balazs Keri <1.int32@gmail.com> | 2019-09-02 11:01:09 +0000 |
|---|---|---|
| committer | Balazs Keri <1.int32@gmail.com> | 2019-09-02 11:01:09 +0000 |
| commit | b06b14ba8cf32c16119bea9252468dea58a61200 (patch) | |
| tree | 546ecf7b9a7c050eab5fc66da8d4b357fbcfbeb3 /clang/unittests | |
| parent | 1aab62762f6658a6955d9bed719a345702f2bb56 (diff) | |
| download | bcm5719-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.cpp | 122 |
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 |

