https://github.com/ChuanqiXu9 updated 
https://github.com/llvm/llvm-project/pull/195983

>From c54b8fcb7d7760929a92599a1e08d7342c24373e Mon Sep 17 00:00:00 2001
From: Chuanqi Xu <[email protected]>
Date: Tue, 7 Apr 2026 15:04:49 +0800
Subject: [PATCH 1/5] Reland [C++20] [Modules] Don't profiling the callee of
 CXXFoldExpr (#190732)

Close https://github.com/llvm/llvm-project/issues/190333

For the test case, the root cause of the problem is, the compiler
thought the declaration of `operator &&` in consumer.cpp may change the
meaning of '&&' in the requrie clause of `F::operator()`. But it doesn't
make sense. Here we skip profiling the callee to solve the problem. Note
that we've already record the kind of the operator. So '&&' and '||'
won't be confused.

---

See the discussion in https://github.com/llvm/llvm-project/pull/194283

For the new found pattern that we may have other binary operator (e.g.,
operator +) in the require clause, e.g.,

```C++
template <typename T, typename U>
    requires requires(T t, U u) { t + u; }
  void operator()(T, U) {}
```

This is a new problem and we need to solve it in other PR.
---
 clang/lib/AST/StmtProfile.cpp                 | 32 ++++++++++++++++-
 .../callable-require-clause-merge.cppm        | 35 +++++++++++++++++++
 clang/test/Modules/polluted-operator.cppm     |  7 ----
 .../diagnose-redefinition-fold-expr.cpp       |  6 ++++
 4 files changed, 72 insertions(+), 8 deletions(-)
 create mode 100644 clang/test/Modules/callable-require-clause-merge.cppm
 create mode 100644 clang/test/SemaCXX/diagnose-redefinition-fold-expr.cpp

diff --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp
index 8219e57644be6..c3bdcb9a2e60d 100644
--- a/clang/lib/AST/StmtProfile.cpp
+++ b/clang/lib/AST/StmtProfile.cpp
@@ -2400,7 +2400,37 @@ void StmtProfiler::VisitMaterializeTemporaryExpr(
 }
 
 void StmtProfiler::VisitCXXFoldExpr(const CXXFoldExpr *S) {
-  VisitExpr(S);
+  VisitStmtNoChildren(S);
+  // We intentionally not profile the callee sub-expression
+  // to keep the profiling result stable across different
+  // context.
+  //
+  // "a.h"
+  //
+  //   struct F {
+  //     template <typename... T> requires ((sizeof(T) > 0) && ...)
+  //     void operator()(T...) {}
+  //   } f;
+  //
+  // and
+  //
+  // "c.h"
+  //
+  //   void operator&&(struct X, struct X);
+  //   #include "a.h"
+  //
+  // Here we might give different profiling results if we profile
+  // the callee sub-expression, which is nullptr in the first case
+  // an UnresolvedLookupExpr in the second case where there is a
+  // global operator&& operator that pollutes the fold expression.
+  if (S->getLHS())
+    Visit(S->getLHS());
+  else
+    ID.AddInteger(0);
+  if (S->getRHS())
+    Visit(S->getRHS());
+  else
+    ID.AddInteger(0);
   ID.AddInteger(S->getOperator());
 }
 
diff --git a/clang/test/Modules/callable-require-clause-merge.cppm 
b/clang/test/Modules/callable-require-clause-merge.cppm
new file mode 100644
index 0000000000000..ae49dd7a58542
--- /dev/null
+++ b/clang/test/Modules/callable-require-clause-merge.cppm
@@ -0,0 +1,35 @@
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: split-file %s %t
+//
+// RUN: %clang_cc1 -std=c++20 %t/mymod.cppm -emit-module-interface -o 
%t/mymod.pcm
+// RUN: %clang_cc1 -std=c++20 %t/consumer.cpp -fprebuilt-module-path=%t 
-fsyntax-only -verify
+//
+// RUN: %clang_cc1 -std=c++20 %t/mymod.cppm -emit-reduced-module-interface -o 
%t/mymod.pcm
+// RUN: %clang_cc1 -std=c++20 %t/consumer.cpp -fprebuilt-module-path=%t 
-fsyntax-only -verify
+
+// RUN: %clang_cc1 -std=c++20 -fskip-odr-check-in-gmf %t/mymod.cppm 
-emit-module-interface -o %t/mymod.pcm
+// RUN: %clang_cc1 -std=c++20 -fskip-odr-check-in-gmf %t/consumer.cpp 
-fprebuilt-module-path=%t -fsyntax-only -verify
+//
+// RUN: %clang_cc1 -std=c++20 -fskip-odr-check-in-gmf %t/mymod.cppm 
-emit-reduced-module-interface -o %t/mymod.pcm
+// RUN: %clang_cc1 -std=c++20 -fskip-odr-check-in-gmf %t/consumer.cpp 
-fprebuilt-module-path=%t -fsyntax-only -verify
+
+//--- r.h
+struct F {
+  template <typename... T> requires ((sizeof(T) > 0) && ...)
+  void operator()(T...) {}
+} f;
+
+//--- mymod.cppm
+module;
+#include "r.h"
+export module mymod;
+export using ::f;
+
+//--- consumer.cpp
+// expected-no-diagnostics
+void operator&&(struct X, struct X);
+#include "r.h"
+import mymod;
+
+void g() { f(); }
diff --git a/clang/test/Modules/polluted-operator.cppm 
b/clang/test/Modules/polluted-operator.cppm
index 45cc5e37d6a64..e81a63c3e03de 100644
--- a/clang/test/Modules/polluted-operator.cppm
+++ b/clang/test/Modules/polluted-operator.cppm
@@ -49,8 +49,6 @@ namespace std
 
 //--- a.cppm
 module;
-// The operator&& defined in 'foo.h' will pollute the 
-// expression '__is_trivial(_Types) && ...' in bar.h
 #include "foo.h"
 #include "bar.h"
 export module a;
@@ -71,9 +69,4 @@ export namespace std {
   using std::operator&&;
 }
 
-#ifdef SKIP_ODR_CHECK_IN_GMF
 // expected-no-diagnostics
-#else
-// expected-error@* {{has different definitions in different modules; first 
difference is defined here found data member '_S_copy_ctor' with an 
initializer}}
-// expected-note@* {{but in 'a.<global>' found data member '_S_copy_ctor' with 
a different initializer}}
-#endif
diff --git a/clang/test/SemaCXX/diagnose-redefinition-fold-expr.cpp 
b/clang/test/SemaCXX/diagnose-redefinition-fold-expr.cpp
new file mode 100644
index 0000000000000..2c43eb7a16d8a
--- /dev/null
+++ b/clang/test/SemaCXX/diagnose-redefinition-fold-expr.cpp
@@ -0,0 +1,6 @@
+// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify %s
+
+template <typename... T> requires ((sizeof(T) > 0) && ...) void f() {} // 
expected-note{{previous definition is here}}
+class A;
+void operator&&(A, A);
+template <typename... T> requires ((sizeof(T) > 0) && ...) void f() {} // 
expected-error{{redefinition of 'f'}}

>From 43088c3d1c70c59db3eded3f29640b26c6284c14 Mon Sep 17 00:00:00 2001
From: Chuanqi Xu <[email protected]>
Date: Fri, 8 May 2026 09:50:44 +0800
Subject: [PATCH 2/5] update

---
 clang/lib/AST/StmtProfile.cpp | 29 +++++++++--------------------
 1 file changed, 9 insertions(+), 20 deletions(-)

diff --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp
index c3bdcb9a2e60d..eb25e5260fd1a 100644
--- a/clang/lib/AST/StmtProfile.cpp
+++ b/clang/lib/AST/StmtProfile.cpp
@@ -2401,28 +2401,17 @@ void StmtProfiler::VisitMaterializeTemporaryExpr(
 
 void StmtProfiler::VisitCXXFoldExpr(const CXXFoldExpr *S) {
   VisitStmtNoChildren(S);
-  // We intentionally not profile the callee sub-expression
-  // to keep the profiling result stable across different
-  // context.
+  // The callee sub-expression is not part of how the expression is written,
+  // so it's not added to the profile.
   //
-  // "a.h"
+  // Example:
+  // template <typename... T> requires ((sizeof(T) > 0) && ...) void f() {}
+  // class A;
+  // void operator&&(A, A);
+  // template <typename... T> requires ((sizeof(T) > 0) && ...) void f() {}
   //
-  //   struct F {
-  //     template <typename... T> requires ((sizeof(T) > 0) && ...)
-  //     void operator()(T...) {}
-  //   } f;
-  //
-  // and
-  //
-  // "c.h"
-  //
-  //   void operator&&(struct X, struct X);
-  //   #include "a.h"
-  //
-  // Here we might give different profiling results if we profile
-  // the callee sub-expression, which is nullptr in the first case
-  // an UnresolvedLookupExpr in the second case where there is a
-  // global operator&& operator that pollutes the fold expression.
+  // Both definitions have identically written fold expressions, but semantic
+  // analysis adds the overloaded operator to the second one.
   if (S->getLHS())
     Visit(S->getLHS());
   else

>From 9c511e2b401bb9245d4bfa8cc31de11b131d4376 Mon Sep 17 00:00:00 2001
From: Chuanqi Xu <[email protected]>
Date: Fri, 8 May 2026 10:30:51 +0800
Subject: [PATCH 3/5] remove modules test

---
 .../callable-require-clause-merge.cppm        | 35 -------------------
 1 file changed, 35 deletions(-)
 delete mode 100644 clang/test/Modules/callable-require-clause-merge.cppm

diff --git a/clang/test/Modules/callable-require-clause-merge.cppm 
b/clang/test/Modules/callable-require-clause-merge.cppm
deleted file mode 100644
index ae49dd7a58542..0000000000000
--- a/clang/test/Modules/callable-require-clause-merge.cppm
+++ /dev/null
@@ -1,35 +0,0 @@
-// RUN: rm -rf %t
-// RUN: mkdir -p %t
-// RUN: split-file %s %t
-//
-// RUN: %clang_cc1 -std=c++20 %t/mymod.cppm -emit-module-interface -o 
%t/mymod.pcm
-// RUN: %clang_cc1 -std=c++20 %t/consumer.cpp -fprebuilt-module-path=%t 
-fsyntax-only -verify
-//
-// RUN: %clang_cc1 -std=c++20 %t/mymod.cppm -emit-reduced-module-interface -o 
%t/mymod.pcm
-// RUN: %clang_cc1 -std=c++20 %t/consumer.cpp -fprebuilt-module-path=%t 
-fsyntax-only -verify
-
-// RUN: %clang_cc1 -std=c++20 -fskip-odr-check-in-gmf %t/mymod.cppm 
-emit-module-interface -o %t/mymod.pcm
-// RUN: %clang_cc1 -std=c++20 -fskip-odr-check-in-gmf %t/consumer.cpp 
-fprebuilt-module-path=%t -fsyntax-only -verify
-//
-// RUN: %clang_cc1 -std=c++20 -fskip-odr-check-in-gmf %t/mymod.cppm 
-emit-reduced-module-interface -o %t/mymod.pcm
-// RUN: %clang_cc1 -std=c++20 -fskip-odr-check-in-gmf %t/consumer.cpp 
-fprebuilt-module-path=%t -fsyntax-only -verify
-
-//--- r.h
-struct F {
-  template <typename... T> requires ((sizeof(T) > 0) && ...)
-  void operator()(T...) {}
-} f;
-
-//--- mymod.cppm
-module;
-#include "r.h"
-export module mymod;
-export using ::f;
-
-//--- consumer.cpp
-// expected-no-diagnostics
-void operator&&(struct X, struct X);
-#include "r.h"
-import mymod;
-
-void g() { f(); }

>From 5ffea11bc11f452e29718cc341583f3bb553003d Mon Sep 17 00:00:00 2001
From: Chuanqi Xu <[email protected]>
Date: Fri, 8 May 2026 10:44:04 +0800
Subject: [PATCH 4/5] Rename newly introduced test

---
 .../SemaCXX/{diagnose-redefinition-fold-expr.cpp => GH190333.cpp} | 0
 1 file changed, 0 insertions(+), 0 deletions(-)
 rename clang/test/SemaCXX/{diagnose-redefinition-fold-expr.cpp => 
GH190333.cpp} (100%)

diff --git a/clang/test/SemaCXX/diagnose-redefinition-fold-expr.cpp 
b/clang/test/SemaCXX/GH190333.cpp
similarity index 100%
rename from clang/test/SemaCXX/diagnose-redefinition-fold-expr.cpp
rename to clang/test/SemaCXX/GH190333.cpp

>From 3fb97439b475d29d5bf34bffb935ada9f7852e02 Mon Sep 17 00:00:00 2001
From: Chuanqi Xu <[email protected]>
Date: Fri, 8 May 2026 11:14:09 +0800
Subject: [PATCH 5/5] remove polluted-operator.cppm test

---
 clang/test/Modules/polluted-operator.cppm | 72 -----------------------
 1 file changed, 72 deletions(-)
 delete mode 100644 clang/test/Modules/polluted-operator.cppm

diff --git a/clang/test/Modules/polluted-operator.cppm 
b/clang/test/Modules/polluted-operator.cppm
deleted file mode 100644
index e81a63c3e03de..0000000000000
--- a/clang/test/Modules/polluted-operator.cppm
+++ /dev/null
@@ -1,72 +0,0 @@
-// RUN: rm -rf %t
-// RUN: mkdir -p %t
-// RUN: split-file %s %t
-//
-// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/a.cppm -o %t/a.pcm
-// RUN: %clang_cc1 -std=c++20 %t/b.cppm -fprebuilt-module-path=%t 
-emit-module-interface -o %t/b.pcm -verify
-//
-// Testing the behavior of `-fskip-odr-check-in-gmf`
-// RUN: %clang_cc1 -std=c++20 -fskip-odr-check-in-gmf  -emit-module-interface 
%t/a.cppm -o \
-// RUN:   %t/a.pcm
-// RUN: %clang_cc1 -std=c++20 -fskip-odr-check-in-gmf  %t/b.cppm 
-fprebuilt-module-path=%t \
-// RUN:   -emit-module-interface -DSKIP_ODR_CHECK_IN_GMF -o %t/b.pcm -verify
-
-// RUN: %clang_cc1 -std=c++20 -emit-reduced-module-interface %t/a.cppm -o 
%t/a.pcm
-// RUN: %clang_cc1 -std=c++20 %t/b.cppm -fprebuilt-module-path=%t 
-emit-reduced-module-interface \
-// RUN:     -o %t/b.pcm -verify -DREDUCED
-
-//--- foo.h
-
-namespace std
-{
-    template<class _Dom1>
-    void operator &&(_Dom1 __v, _Dom1 __w)
-    { 
-        return;
-    }
-}
-
-//--- bar.h
-namespace std 
-{
-  template<typename... _Types>
-    struct _Traits
-    {
-      static constexpr bool _S_copy_ctor =
-   (__is_trivial(_Types) && ...);
-    };
-
-  template<typename... _Types>
-    struct variant
-    {
-      void
-      swap(variant& __rhs)
-      noexcept((__is_trivial(_Types) && ...))
-      {
-      }
-    };
-}
-
-//--- a.cppm
-module;
-#include "foo.h"
-#include "bar.h"
-export module a;
-export namespace std {
-  using std::variant;
-  using std::_Traits;
-  using std::operator&&;
-}
-
-//--- b.cppm
-module;
-#include "bar.h"
-export module b;
-import a;
-export namespace std {
-  using std::variant;
-  using std::_Traits;
-  using std::operator&&;
-}
-
-// expected-no-diagnostics

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to