https://github.com/ChuanqiXu9 created https://github.com/llvm/llvm-project/pull/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. >From 4d1fb62879f4035b2862cb6d3c68ec32355cc4bd Mon Sep 17 00:00:00 2001 From: Chuanqi Xu <[email protected]> Date: Tue, 7 Apr 2026 13:43:10 +0800 Subject: [PATCH] [C++20] [Modules] Don't profiling the callee of CXXFoldExpr 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. --- clang/lib/AST/StmtProfile.cpp | 30 +++++++++++++++- .../callable-require-clause-merge.cppm | 35 +++++++++++++++++++ clang/test/Modules/polluted-operator.cppm | 7 ---- 3 files changed, 64 insertions(+), 8 deletions(-) create mode 100644 clang/test/Modules/callable-require-clause-merge.cppm diff --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp index e8c1f8a8ecb5f..af27a928edff6 100644 --- a/clang/lib/AST/StmtProfile.cpp +++ b/clang/lib/AST/StmtProfile.cpp @@ -2390,7 +2390,35 @@ void StmtProfiler::VisitMaterializeTemporaryExpr( } void StmtProfiler::VisitCXXFoldExpr(const CXXFoldExpr *S) { - VisitExpr(S); + // For CXXFoldExpr, not profile the call expression as it may + // be affected by the context. e.g., + // + // "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 may give different profile results to F::operator() in + // "c.h" vs other use cases of "a.h". This is problematic in + // cases where we may have expression coming from different + // headers, e.g., modules. + 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 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
