Author: Balázs Kéri Date: 2022-12-21T09:58:50+01:00 New Revision: 13417808474cacc064b90726705862a650c0b28a
URL: https://github.com/llvm/llvm-project/commit/13417808474cacc064b90726705862a650c0b28a DIFF: https://github.com/llvm/llvm-project/commit/13417808474cacc064b90726705862a650c0b28a.diff LOG: [clang][AST] Compare UnresolvedLookupExpr in structural equivalence. Reviewed By: gamesh411 Differential Revision: https://reviews.llvm.org/D136848 Added: Modified: clang/lib/AST/ASTStructuralEquivalence.cpp clang/unittests/AST/StructuralEquivalenceTest.cpp Removed: ################################################################################ diff --git a/clang/lib/AST/ASTStructuralEquivalence.cpp b/clang/lib/AST/ASTStructuralEquivalence.cpp index e234e083813e9..46321f5ba7cf9 100644 --- a/clang/lib/AST/ASTStructuralEquivalence.cpp +++ b/clang/lib/AST/ASTStructuralEquivalence.cpp @@ -102,6 +102,9 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, const TemplateArgument &Arg1, const TemplateArgument &Arg2); +static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, + const TemplateArgumentLoc &Arg1, + const TemplateArgumentLoc &Arg2); static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, NestedNameSpecifier *NNS1, NestedNameSpecifier *NNS2); @@ -340,6 +343,30 @@ class StmtComparer { return true; } + bool IsStmtEquivalent(const OverloadExpr *E1, const OverloadExpr *E2) { + if (!IsStructurallyEquivalent(Context, E1->getName(), E2->getName())) + return false; + + if (static_cast<bool>(E1->getQualifier()) != + static_cast<bool>(E2->getQualifier())) + return false; + if (E1->getQualifier() && + !IsStructurallyEquivalent(Context, E1->getQualifier(), + E2->getQualifier())) + return false; + + if (E1->getNumTemplateArgs() != E2->getNumTemplateArgs()) + return false; + const TemplateArgumentLoc *Args1 = E1->getTemplateArgs(); + const TemplateArgumentLoc *Args2 = E2->getTemplateArgs(); + for (unsigned int ArgI = 0, ArgN = E1->getNumTemplateArgs(); ArgI < ArgN; + ++ArgI) + if (!IsStructurallyEquivalent(Context, Args1[ArgI], Args2[ArgI])) + return false; + + return true; + } + /// End point of the traversal chain. bool TraverseStmt(const Stmt *S1, const Stmt *S2) { return true; } @@ -599,6 +626,14 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, return true; } +/// Determine whether two template argument locations are equivalent. +static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, + const TemplateArgumentLoc &Arg1, + const TemplateArgumentLoc &Arg2) { + return IsStructurallyEquivalent(Context, Arg1.getArgument(), + Arg2.getArgument()); +} + /// Determine structural equivalence for the common part of array /// types. static bool IsArrayStructurallyEquivalent(StructuralEquivalenceContext &Context, diff --git a/clang/unittests/AST/StructuralEquivalenceTest.cpp b/clang/unittests/AST/StructuralEquivalenceTest.cpp index 3f89bcef73729..03616d7197ea8 100644 --- a/clang/unittests/AST/StructuralEquivalenceTest.cpp +++ b/clang/unittests/AST/StructuralEquivalenceTest.cpp @@ -2125,5 +2125,128 @@ TEST_F(StructuralEquivalenceStmtTest, UnaryOperatorDifferentOps) { EXPECT_FALSE(testStructuralMatch(t)); } +TEST_F(StructuralEquivalenceStmtTest, UnresolvedLookupDifferentName) { + auto t = makeStmts( + R"( + void f1(int); + template <typename T> + void f(T t) { + f1(t); + } + void g() { f<int>(1); } + )", + R"( + void f2(int); + template <typename T> + void f(T t) { + f2(t); + } + void g() { f<int>(1); } + )", + Lang_CXX03, unresolvedLookupExpr()); + EXPECT_FALSE(testStructuralMatch(t)); +} + +TEST_F(StructuralEquivalenceStmtTest, UnresolvedLookupDifferentQualifier) { + auto t = makeStmts( + R"( + struct X { + static void g(int); + static void g(char); + }; + + template <typename T> + void f(T t) { + X::g(t); + } + + void g() { f<int>(1); } + )", + R"( + struct Y { + static void g(int); + static void g(char); + }; + + template <typename T> + void f(T t) { + Y::g(t); + } + + void g() { f<int>(1); } + )", + Lang_CXX03, unresolvedLookupExpr()); + EXPECT_FALSE(testStructuralMatch(t)); +} + +TEST_F(StructuralEquivalenceStmtTest, + UnresolvedLookupDifferentTemplateArgument) { + auto t = makeStmts( + R"( + struct A {}; + template<typename T1, typename T2> + void g() {} + + template <typename T> + void f() { + g<A, T>(); + } + + void h() { f<int>(); } + )", + R"( + struct B {}; + template<typename T1, typename T2> + void g() {} + + template <typename T> + void f() { + g<B, T>(); + } + + void h() { f<int>(); } + )", + Lang_CXX03, unresolvedLookupExpr()); + EXPECT_FALSE(testStructuralMatch(t)); +} + +TEST_F(StructuralEquivalenceStmtTest, UnresolvedLookup) { + auto t = makeStmts( + R"( + struct A {}; + struct B { + template<typename T1, typename T2> + static void g(int) {}; + template<typename T1, typename T2> + static void g(char) {}; + }; + + template <typename T1, typename T2> + void f(T2 x) { + B::g<A, T1>(x); + } + + void g() { f<char, int>(1); } + )", + R"( + struct A {}; + struct B { + template<typename T1, typename T2> + static void g(int) {}; + template<typename T1, typename T2> + static void g(char) {}; + }; + + template <typename T1, typename T2> + void f(T2 x) { + B::g<A, T1>(x); + } + + void g() { f<char, int>(1); } + )", + Lang_CXX03, unresolvedLookupExpr()); + EXPECT_TRUE(testStructuralMatch(t)); +} + } // end namespace ast_matchers } // end namespace clang _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits