[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