[llvm-branch-commits] [clang] 823afe0 - Reland [C++20] [Modules] Don't profiling the callee of CXXFoldExpr (#190732) (#195983)
Cullen Rhodes via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Tue May 26 01:20:46 PDT 2026
Author: Chuanqi Xu
Date: 2026-05-26T08:20:37Z
New Revision: 823afe046164918015c2907ca840b4ff45b80343
URL: https://github.com/llvm/llvm-project/commit/823afe046164918015c2907ca840b4ff45b80343
DIFF: https://github.com/llvm/llvm-project/commit/823afe046164918015c2907ca840b4ff45b80343.diff
LOG: Reland [C++20] [Modules] Don't profiling the callee of CXXFoldExpr (#190732) (#195983)
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.
(cherry picked from commit 2751c7ed066d08d3c801670e6c5629a39ddfe90e)
Added:
clang/test/SemaCXX/GH190333.cpp
Modified:
clang/lib/AST/StmtProfile.cpp
Removed:
clang/test/Modules/polluted-operator.cppm
################################################################################
diff --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp
index a626d043676e0..03b5563854f83 100644
--- a/clang/lib/AST/StmtProfile.cpp
+++ b/clang/lib/AST/StmtProfile.cpp
@@ -2369,7 +2369,26 @@ void StmtProfiler::VisitMaterializeTemporaryExpr(
}
void StmtProfiler::VisitCXXFoldExpr(const CXXFoldExpr *S) {
- VisitExpr(S);
+ VisitStmtNoChildren(S);
+ // The callee sub-expression is not part of how the expression is written,
+ // so it's not added to the profile.
+ //
+ // 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() {}
+ //
+ // 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
+ ID.AddInteger(0);
+ if (S->getRHS())
+ Visit(S->getRHS());
+ else
+ ID.AddInteger(0);
ID.AddInteger(S->getOperator());
}
diff --git a/clang/test/Modules/polluted-operator.cppm b/clang/test/Modules/polluted-operator.cppm
deleted file mode 100644
index 45cc5e37d6a64..0000000000000
--- a/clang/test/Modules/polluted-operator.cppm
+++ /dev/null
@@ -1,79 +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;
-// 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;
-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&&;
-}
-
-#ifdef SKIP_ODR_CHECK_IN_GMF
-// expected-no-diagnostics
-#else
-// expected-error@* {{has
diff erent definitions in
diff erent modules; first
diff erence 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
diff erent initializer}}
-#endif
diff --git a/clang/test/SemaCXX/GH190333.cpp b/clang/test/SemaCXX/GH190333.cpp
new file mode 100644
index 0000000000000..2c43eb7a16d8a
--- /dev/null
+++ b/clang/test/SemaCXX/GH190333.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'}}
More information about the llvm-branch-commits
mailing list