@@ -134,8 +134,8 @@ struct StructuralEquivalenceTest : ::testing::Test {
134
134
135
135
bool testStructuralMatch (Decl *D0, Decl *D1,
136
136
bool IgnoreTemplateParmDepth = false ) {
137
- llvm::DenseSet<std::pair<Decl *, Decl *>> NonEquivalentDecls01;
138
- llvm::DenseSet<std::pair<Decl *, Decl *>> NonEquivalentDecls10;
137
+ StructuralEquivalenceContext::NonEquivalentDeclSet NonEquivalentDecls01;
138
+ StructuralEquivalenceContext::NonEquivalentDeclSet NonEquivalentDecls10;
139
139
StructuralEquivalenceContext Ctx01 (
140
140
D0->getASTContext (), D1->getASTContext (), NonEquivalentDecls01,
141
141
StructuralEquivalenceKind::Default, /* StrictTypeSpelling=*/ false ,
@@ -153,8 +153,8 @@ struct StructuralEquivalenceTest : ::testing::Test {
153
153
}
154
154
155
155
bool testStructuralMatch (StmtWithASTContext S0, StmtWithASTContext S1) {
156
- llvm::DenseSet<std::pair<Decl *, Decl *>> NonEquivalentDecls01;
157
- llvm::DenseSet<std::pair<Decl *, Decl *>> NonEquivalentDecls10;
156
+ StructuralEquivalenceContext::NonEquivalentDeclSet NonEquivalentDecls01;
157
+ StructuralEquivalenceContext::NonEquivalentDeclSet NonEquivalentDecls10;
158
158
StructuralEquivalenceContext Ctx01 (
159
159
*S0.Context , *S1.Context , NonEquivalentDecls01,
160
160
StructuralEquivalenceKind::Default, false , false );
@@ -1792,7 +1792,7 @@ TEST_F(
1792
1792
EXPECT_FALSE (testStructuralMatch (t));
1793
1793
}
1794
1794
struct StructuralEquivalenceCacheTest : public StructuralEquivalenceTest {
1795
- llvm::DenseSet<std::pair<Decl *, Decl *>> NonEquivalentDecls;
1795
+ StructuralEquivalenceContext::NonEquivalentDeclSet NonEquivalentDecls;
1796
1796
1797
1797
template <typename NodeType, typename MatcherType>
1798
1798
std::pair<NodeType *, NodeType *>
@@ -1804,8 +1804,10 @@ struct StructuralEquivalenceCacheTest : public StructuralEquivalenceTest {
1804
1804
}
1805
1805
1806
1806
template <typename NodeType>
1807
- bool isInNonEqCache (std::pair<NodeType *, NodeType *> D) {
1808
- return NonEquivalentDecls.count (D) > 0 ;
1807
+ bool isInNonEqCache (std::pair<NodeType *, NodeType *> D,
1808
+ bool IgnoreTemplateParmDepth = false ) {
1809
+ return NonEquivalentDecls.count (
1810
+ std::make_tuple (D.first , D.second , IgnoreTemplateParmDepth)) > 0 ;
1809
1811
}
1810
1812
};
1811
1813
@@ -2015,6 +2017,78 @@ TEST_F(StructuralEquivalenceCacheTest, Cycle) {
2015
2017
findDeclPair<FunctionDecl>(TU, functionDecl (hasName (" x" )))));
2016
2018
}
2017
2019
2020
+ TEST_F (StructuralEquivalenceCacheTest, TemplateParmDepth) {
2021
+ // In 'friend struct Y' ClassTemplateDecl has the TU as parent context.
2022
+ // This declaration has template depth 1 (it is already inside a template).
2023
+ // It has not a previous declaration and is an "undeclared" friend.
2024
+ //
2025
+ // Second TU has a specialization of 'struct X'.
2026
+ // In this case 'friend struct Y' has the ClassTemplateSpecializationDecl as
2027
+ // parent. It has template depth 0 (it is in the specialization). It has the
2028
+ // first 'struct Y' declaration as previous declaration and canonical
2029
+ // declaration.
2030
+ //
2031
+ // When these two 'friend struct Y' are compared, only the template depth is
2032
+ // different.
2033
+ // FIXME: Structural equivalence checks the depth only in types, not in
2034
+ // TemplateParmDecl. For this reason the second 'A1' argument is needed (as a
2035
+ // type) in the template to make the check fail.
2036
+ auto TU = makeTuDecls (
2037
+ R"(
2038
+ template <class A1, A1>
2039
+ struct Y;
2040
+
2041
+ template <class A>
2042
+ struct X {
2043
+ template <class A1, A1>
2044
+ friend struct Y;
2045
+ };
2046
+ )" ,
2047
+ R"(
2048
+ template <class A1, A1>
2049
+ struct Y;
2050
+
2051
+ template <class A>
2052
+ struct X {
2053
+ template <class A1, A1>
2054
+ friend struct Y;
2055
+ };
2056
+
2057
+ X<int> x;
2058
+ )" ,
2059
+ Lang_CXX03);
2060
+
2061
+ auto *D0 = LastDeclMatcher<ClassTemplateDecl>().match (
2062
+ get<0 >(TU), classTemplateDecl (hasName (" Y" ), unless (isImplicit ())));
2063
+ auto *D1 = LastDeclMatcher<ClassTemplateDecl>().match (
2064
+ get<1 >(TU), classTemplateDecl (hasName (" Y" ), unless (isImplicit ())));
2065
+ ASSERT_EQ (D0->getTemplateDepth (), 1u );
2066
+ ASSERT_EQ (D1->getTemplateDepth (), 0u );
2067
+
2068
+ StructuralEquivalenceContext Ctx_NoIgnoreTemplateParmDepth (
2069
+ get<0 >(TU)->getASTContext (), get<1 >(TU)->getASTContext (),
2070
+ NonEquivalentDecls, StructuralEquivalenceKind::Default, false , false ,
2071
+ false , false );
2072
+
2073
+ EXPECT_FALSE (Ctx_NoIgnoreTemplateParmDepth.IsEquivalent (D0, D1));
2074
+
2075
+ Decl *NonEqDecl0 =
2076
+ D0->getCanonicalDecl ()->getTemplateParameters ()->getParam (1 );
2077
+ Decl *NonEqDecl1 =
2078
+ D1->getCanonicalDecl ()->getTemplateParameters ()->getParam (1 );
2079
+ EXPECT_TRUE (isInNonEqCache (std::make_pair (NonEqDecl0, NonEqDecl1), false ));
2080
+ EXPECT_FALSE (isInNonEqCache (std::make_pair (NonEqDecl0, NonEqDecl1), true ));
2081
+
2082
+ StructuralEquivalenceContext Ctx_IgnoreTemplateParmDepth (
2083
+ get<0 >(TU)->getASTContext (), get<1 >(TU)->getASTContext (),
2084
+ NonEquivalentDecls, StructuralEquivalenceKind::Default, false , false ,
2085
+ false , true );
2086
+
2087
+ EXPECT_TRUE (Ctx_IgnoreTemplateParmDepth.IsEquivalent (D0, D1));
2088
+
2089
+ EXPECT_FALSE (isInNonEqCache (std::make_pair (NonEqDecl0, NonEqDecl1), true ));
2090
+ }
2091
+
2018
2092
struct StructuralEquivalenceStmtTest : StructuralEquivalenceTest {};
2019
2093
2020
2094
// / Fallback matcher to be used only when there is no specific matcher for a
0 commit comments