[clang] 1341780 - [clang][AST] Compare UnresolvedLookupExpr in structural equivalence.
Balázs Kéri via cfe-commits
cfe-commits at lists.llvm.org
Wed Dec 21 00:59:29 PST 2022
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
More information about the cfe-commits
mailing list