diff --git a/clang/lib/AST/ASTStructuralEquivalence.cpp b/clang/lib/AST/ASTStructuralEquivalence.cpp index d56bf21b459e03..37555c324282fe 100644 --- a/clang/lib/AST/ASTStructuralEquivalence.cpp +++ b/clang/lib/AST/ASTStructuralEquivalence.cpp @@ -348,6 +348,15 @@ class StmtComparer { return true; } + bool IsStmtEquivalent(const CXXDependentScopeMemberExpr *E1, + const CXXDependentScopeMemberExpr *E2) { + if (!IsStructurallyEquivalent(Context, E1->getMember(), E2->getMember())) { + return false; + } + return IsStructurallyEquivalent(Context, E1->getBaseType(), + E2->getBaseType()); + } + bool IsStmtEquivalent(const UnaryExprOrTypeTraitExpr *E1, const UnaryExprOrTypeTraitExpr *E2) { if (E1->getKind() != E2->getKind()) @@ -1997,7 +2006,10 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, } return false; } - + if (!Context.IgnoreTemplateParmDepth && D1->getDepth() != D2->getDepth()) + return false; + if (D1->getIndex() != D2->getIndex()) + return false; // Check types. if (!IsStructurallyEquivalent(Context, D1->getType(), D2->getType())) { if (Context.Complain) { diff --git a/clang/unittests/AST/StructuralEquivalenceTest.cpp b/clang/unittests/AST/StructuralEquivalenceTest.cpp index 91dd717d7b25e5..952c83be0cb649 100644 --- a/clang/unittests/AST/StructuralEquivalenceTest.cpp +++ b/clang/unittests/AST/StructuralEquivalenceTest.cpp @@ -1877,6 +1877,34 @@ TEST_F(StructuralEquivalenceCacheTest, VarDeclWithDifferentStorageClassNoEq) { EXPECT_FALSE(Ctx.IsEquivalent(Var.first, Var.second)); } +TEST_F(StructuralEquivalenceCacheTest, + NonTypeTemplateParmWithDifferentPositionNoEq) { + auto TU = makeTuDecls( + R"( + template + struct A { + template + void foo() {} + }; + )", + R"( + template + struct A { + template + void foo() {} + }; + )", + Lang_CXX03); + + StructuralEquivalenceContext Ctx( + get<0>(TU)->getASTContext(), get<1>(TU)->getASTContext(), + NonEquivalentDecls, StructuralEquivalenceKind::Default, false, false); + + auto NTTP = findDeclPair( + TU, nonTypeTemplateParmDecl(hasName("T"))); + EXPECT_FALSE(Ctx.IsEquivalent(NTTP.first, NTTP.second)); +} + TEST_F(StructuralEquivalenceCacheTest, VarDeclWithInitNoEq) { auto TU = makeTuDecls( R"( @@ -2441,8 +2469,7 @@ TEST_F(StructuralEquivalenceStmtTest, NonTypeTemplateParm) { void foo(A); )", Lang_CXX11); - // FIXME: These should not match, - EXPECT_TRUE(testStructuralMatch(t)); + EXPECT_FALSE(testStructuralMatch(t)); } TEST_F(StructuralEquivalenceStmtTest, UnresolvedLookupDifferentName) { @@ -2595,5 +2622,31 @@ TEST_F(StructuralEquivalenceStmtTest, DeclRefExpr) { EXPECT_FALSE(testStructuralMatch(t)); } +TEST_F(StructuralEquivalenceCacheTest, CXXDependentScopeMemberExprNoEq) { + auto S = makeStmts( + R"( + template + void foo() { + (void)T().x; + } + struct A { int x; }; + void bar() { + foo(); + } + )", + R"( + template + void foo() { + (void)T().y; + } + struct A { int y; }; + void bar() { + foo(); + } + )", + Lang_CXX11, cxxDependentScopeMemberExpr()); + EXPECT_FALSE(testStructuralMatch(S)); +} + } // end namespace ast_matchers } // end namespace clang