[clang] e648603 - [C++20] [Modules] Reference all the possible declarations for ADL
Chuanqi Xu via cfe-commits
cfe-commits at lists.llvm.org
Thu Jun 20 20:06:18 PDT 2024
Author: Chuanqi Xu
Date: 2024-06-21T11:04:53+08:00
New Revision: e6486030340ea5756bec43a633567ed6411668c3
URL: https://github.com/llvm/llvm-project/commit/e6486030340ea5756bec43a633567ed6411668c3
DIFF: https://github.com/llvm/llvm-project/commit/e6486030340ea5756bec43a633567ed6411668c3.diff
LOG: [C++20] [Modules] Reference all the possible declarations for ADL
In no transitive change mode, the unresolved ADL may not
be referenced, then it is problematic if the change didn't get
propagated correctly. This patch add references to all the possible
module files for the unresolved ADL to solve the problem.
Added:
clang/test/Modules/transitive-adl-change.cppm
Modified:
clang/lib/Serialization/ASTWriterStmt.cpp
Removed:
################################################################################
diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp
index 12610c4ffe1c5..ea499019c9d16 100644
--- a/clang/lib/Serialization/ASTWriterStmt.cpp
+++ b/clang/lib/Serialization/ASTWriterStmt.cpp
@@ -19,6 +19,7 @@
#include "clang/AST/ExprOpenMP.h"
#include "clang/AST/StmtVisitor.h"
#include "clang/Lex/Token.h"
+#include "clang/Serialization/ASTReader.h"
#include "clang/Serialization/ASTRecordWriter.h"
#include "llvm/Bitstream/BitstreamWriter.h"
using namespace clang;
@@ -2099,6 +2100,22 @@ void ASTStmtWriter::VisitUnresolvedLookupExpr(UnresolvedLookupExpr *E) {
CurrentPackingBits.addBit(E->requiresADL());
Record.AddDeclRef(E->getNamingClass());
Code = serialization::EXPR_CXX_UNRESOLVED_LOOKUP;
+
+ if (Writer.isWritingStdCXXNamedModules() && Writer.getChain()) {
+ // Referencing all the possible declarations to make sure the change get
+ // propagted.
+ DeclarationName Name = E->getName();
+ for (auto *Found :
+ Writer.getASTContext().getTranslationUnitDecl()->lookup(Name))
+ if (Found->isFromASTFile())
+ Writer.GetDeclRef(Found);
+
+ llvm::SmallVector<NamespaceDecl *> ExternalNSs;
+ Writer.getChain()->ReadKnownNamespaces(ExternalNSs);
+ for (auto *NS : ExternalNSs)
+ for (auto *Found : NS->lookup(Name))
+ Writer.GetDeclRef(Found);
+ }
}
void ASTStmtWriter::VisitTypeTraitExpr(TypeTraitExpr *E) {
diff --git a/clang/test/Modules/transitive-adl-change.cppm b/clang/test/Modules/transitive-adl-change.cppm
new file mode 100644
index 0000000000000..bc068f06a2b7b
--- /dev/null
+++ b/clang/test/Modules/transitive-adl-change.cppm
@@ -0,0 +1,112 @@
+// Test that a change related to an ADL can be propagated correctly.
+//
+// RUN: rm -rf %t
+// RUN: split-file %s %t
+//
+// RUN: %clang_cc1 -std=c++20 %t/Common.cppm -emit-reduced-module-interface -o %t/Common.pcm
+//
+// RUN: %clang_cc1 -std=c++20 %t/m-partA.cppm -emit-reduced-module-interface -o %t/m-partA.pcm \
+// RUN: -fmodule-file=Common=%t/Common.pcm
+// RUN: %clang_cc1 -std=c++20 %t/m-partA.v1.cppm -emit-reduced-module-interface -o \
+// RUN: %t/m-partA.v1.pcm -fmodule-file=Common=%t/Common.pcm
+// RUN: %clang_cc1 -std=c++20 %t/m-partB.cppm -emit-reduced-module-interface -o %t/m-partB.pcm
+// RUN: %clang_cc1 -std=c++20 %t/m.cppm -emit-reduced-module-interface -o %t/m.pcm \
+// RUN: -fmodule-file=m:partA=%t/m-partA.pcm -fmodule-file=m:partB=%t/m-partB.pcm \
+// RUN: -fmodule-file=Common=%t/Common.pcm
+// RUN: %clang_cc1 -std=c++20 %t/m.cppm -emit-reduced-module-interface -o %t/m.v1.pcm \
+// RUN: -fmodule-file=m:partA=%t/m-partA.v1.pcm -fmodule-file=m:partB=%t/m-partB.pcm \
+// RUN: -fmodule-file=Common=%t/Common.pcm
+//
+// Produce B.pcm and B.v1.pcm
+// RUN: %clang_cc1 -std=c++20 %t/B.cppm -emit-reduced-module-interface -o %t/B.pcm \
+// RUN: -fmodule-file=m=%t/m.pcm -fmodule-file=m:partA=%t/m-partA.pcm \
+// RUN: -fmodule-file=m:partB=%t/m-partB.pcm -fmodule-file=Common=%t/Common.pcm
+// RUN: %clang_cc1 -std=c++20 %t/B.cppm -emit-reduced-module-interface -o %t/B.v1.pcm \
+// RUN: -fmodule-file=m=%t/m.v1.pcm -fmodule-file=m:partA=%t/m-partA.v1.pcm \
+// RUN: -fmodule-file=m:partB=%t/m-partB.pcm -fmodule-file=Common=%t/Common.pcm
+//
+// Verify that both B.pcm and B.v1.pcm can work as expected.
+// RUN: %clang_cc1 -std=c++20 %t/use.cpp -fsyntax-only -verify -fmodule-file=m=%t/m.pcm \
+// RUN: -fmodule-file=m:partA=%t/m-partA.pcm -fmodule-file=m:partB=%t/m-partB.pcm \
+// RUN: -fmodule-file=B=%t/B.pcm -fmodule-file=Common=%t/Common.pcm \
+// RUN: -DEXPECTED_VALUE=false
+// RUN: %clang_cc1 -std=c++20 %t/use.cpp -fsyntax-only -verify -fmodule-file=m=%t/m.v1.pcm \
+// RUN: -fmodule-file=m:partA=%t/m-partA.v1.pcm -fmodule-file=m:partB=%t/m-partB.pcm \
+// RUN: -fmodule-file=B=%t/B.v1.pcm -fmodule-file=Common=%t/Common.pcm \
+// RUN: -DEXPECTED_VALUE=true
+//
+// Since we add new ADL function in m-partA.v1.cppm, B.v1.pcm is expected to not be the same with
+// B.pcm.
+// RUN: not
diff %t/B.pcm %t/B.v1.pcm &> /dev/null
+
+// Test that BMI won't
diff er if it doesn't refer adl.
+// RUN: %clang_cc1 -std=c++20 %t/C.cppm -emit-reduced-module-interface -o %t/C.pcm \
+// RUN: -fmodule-file=m=%t/m.pcm -fmodule-file=m:partA=%t/m-partA.pcm \
+// RUN: -fmodule-file=m:partB=%t/m-partB.pcm -fmodule-file=Common=%t/Common.pcm
+// RUN: %clang_cc1 -std=c++20 %t/C.cppm -emit-reduced-module-interface -o %t/C.v1.pcm \
+// RUN: -fmodule-file=m=%t/m.v1.pcm -fmodule-file=m:partA=%t/m-partA.v1.pcm \
+// RUN: -fmodule-file=m:partB=%t/m-partB.pcm -fmodule-file=Common=%t/Common.pcm
+// RUN:
diff %t/C.pcm %t/C.v1.pcm &> /dev/null
+
+//--- Common.cppm
+export module Common;
+
+export namespace N {
+ struct A {
+ constexpr operator int() {
+ return 43;
+ }
+ };
+}
+
+//--- m-partA.cppm
+export module m:partA;
+import Common;
+
+export namespace N {}
+
+//--- m-partA.v1.cppm
+export module m:partA;
+import Common;
+
+export namespace N {
+constexpr bool adl(A) { return true; }
+}
+
+//--- m-partB.cppm
+export module m:partB;
+
+export constexpr bool adl(int) { return false; }
+
+//--- m.cppm
+export module m;
+export import :partA;
+export import :partB;
+
+//--- B.cppm
+export module B;
+import m;
+
+export template <class C>
+constexpr bool test_adl(C c) {
+ return adl(c);
+}
+
+//--- use.cpp
+// expected-no-diagnostics
+import B;
+import Common;
+
+void test() {
+ N::A a;
+ static_assert(test_adl(a) == EXPECTED_VALUE);
+}
+
+//--- C.cppm
+export module B;
+import m;
+
+export template <class C>
+constexpr bool not_test_adl(C c) {
+ return false;
+}
More information about the cfe-commits
mailing list