Skip to content

Commit e648603

Browse files
committed
[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.
1 parent 7b906d4 commit e648603

File tree

2 files changed

+129
-0
lines changed

2 files changed

+129
-0
lines changed

clang/lib/Serialization/ASTWriterStmt.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "clang/AST/ExprOpenMP.h"
2020
#include "clang/AST/StmtVisitor.h"
2121
#include "clang/Lex/Token.h"
22+
#include "clang/Serialization/ASTReader.h"
2223
#include "clang/Serialization/ASTRecordWriter.h"
2324
#include "llvm/Bitstream/BitstreamWriter.h"
2425
using namespace clang;
@@ -2099,6 +2100,22 @@ void ASTStmtWriter::VisitUnresolvedLookupExpr(UnresolvedLookupExpr *E) {
20992100
CurrentPackingBits.addBit(E->requiresADL());
21002101
Record.AddDeclRef(E->getNamingClass());
21012102
Code = serialization::EXPR_CXX_UNRESOLVED_LOOKUP;
2103+
2104+
if (Writer.isWritingStdCXXNamedModules() && Writer.getChain()) {
2105+
// Referencing all the possible declarations to make sure the change get
2106+
// propagted.
2107+
DeclarationName Name = E->getName();
2108+
for (auto *Found :
2109+
Writer.getASTContext().getTranslationUnitDecl()->lookup(Name))
2110+
if (Found->isFromASTFile())
2111+
Writer.GetDeclRef(Found);
2112+
2113+
llvm::SmallVector<NamespaceDecl *> ExternalNSs;
2114+
Writer.getChain()->ReadKnownNamespaces(ExternalNSs);
2115+
for (auto *NS : ExternalNSs)
2116+
for (auto *Found : NS->lookup(Name))
2117+
Writer.GetDeclRef(Found);
2118+
}
21022119
}
21032120

21042121
void ASTStmtWriter::VisitTypeTraitExpr(TypeTraitExpr *E) {
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
// Test that a change related to an ADL can be propagated correctly.
2+
//
3+
// RUN: rm -rf %t
4+
// RUN: split-file %s %t
5+
//
6+
// RUN: %clang_cc1 -std=c++20 %t/Common.cppm -emit-reduced-module-interface -o %t/Common.pcm
7+
//
8+
// RUN: %clang_cc1 -std=c++20 %t/m-partA.cppm -emit-reduced-module-interface -o %t/m-partA.pcm \
9+
// RUN: -fmodule-file=Common=%t/Common.pcm
10+
// RUN: %clang_cc1 -std=c++20 %t/m-partA.v1.cppm -emit-reduced-module-interface -o \
11+
// RUN: %t/m-partA.v1.pcm -fmodule-file=Common=%t/Common.pcm
12+
// RUN: %clang_cc1 -std=c++20 %t/m-partB.cppm -emit-reduced-module-interface -o %t/m-partB.pcm
13+
// RUN: %clang_cc1 -std=c++20 %t/m.cppm -emit-reduced-module-interface -o %t/m.pcm \
14+
// RUN: -fmodule-file=m:partA=%t/m-partA.pcm -fmodule-file=m:partB=%t/m-partB.pcm \
15+
// RUN: -fmodule-file=Common=%t/Common.pcm
16+
// RUN: %clang_cc1 -std=c++20 %t/m.cppm -emit-reduced-module-interface -o %t/m.v1.pcm \
17+
// RUN: -fmodule-file=m:partA=%t/m-partA.v1.pcm -fmodule-file=m:partB=%t/m-partB.pcm \
18+
// RUN: -fmodule-file=Common=%t/Common.pcm
19+
//
20+
// Produce B.pcm and B.v1.pcm
21+
// RUN: %clang_cc1 -std=c++20 %t/B.cppm -emit-reduced-module-interface -o %t/B.pcm \
22+
// RUN: -fmodule-file=m=%t/m.pcm -fmodule-file=m:partA=%t/m-partA.pcm \
23+
// RUN: -fmodule-file=m:partB=%t/m-partB.pcm -fmodule-file=Common=%t/Common.pcm
24+
// RUN: %clang_cc1 -std=c++20 %t/B.cppm -emit-reduced-module-interface -o %t/B.v1.pcm \
25+
// RUN: -fmodule-file=m=%t/m.v1.pcm -fmodule-file=m:partA=%t/m-partA.v1.pcm \
26+
// RUN: -fmodule-file=m:partB=%t/m-partB.pcm -fmodule-file=Common=%t/Common.pcm
27+
//
28+
// Verify that both B.pcm and B.v1.pcm can work as expected.
29+
// RUN: %clang_cc1 -std=c++20 %t/use.cpp -fsyntax-only -verify -fmodule-file=m=%t/m.pcm \
30+
// RUN: -fmodule-file=m:partA=%t/m-partA.pcm -fmodule-file=m:partB=%t/m-partB.pcm \
31+
// RUN: -fmodule-file=B=%t/B.pcm -fmodule-file=Common=%t/Common.pcm \
32+
// RUN: -DEXPECTED_VALUE=false
33+
// RUN: %clang_cc1 -std=c++20 %t/use.cpp -fsyntax-only -verify -fmodule-file=m=%t/m.v1.pcm \
34+
// RUN: -fmodule-file=m:partA=%t/m-partA.v1.pcm -fmodule-file=m:partB=%t/m-partB.pcm \
35+
// RUN: -fmodule-file=B=%t/B.v1.pcm -fmodule-file=Common=%t/Common.pcm \
36+
// RUN: -DEXPECTED_VALUE=true
37+
//
38+
// Since we add new ADL function in m-partA.v1.cppm, B.v1.pcm is expected to not be the same with
39+
// B.pcm.
40+
// RUN: not diff %t/B.pcm %t/B.v1.pcm &> /dev/null
41+
42+
// Test that BMI won't differ if it doesn't refer adl.
43+
// RUN: %clang_cc1 -std=c++20 %t/C.cppm -emit-reduced-module-interface -o %t/C.pcm \
44+
// RUN: -fmodule-file=m=%t/m.pcm -fmodule-file=m:partA=%t/m-partA.pcm \
45+
// RUN: -fmodule-file=m:partB=%t/m-partB.pcm -fmodule-file=Common=%t/Common.pcm
46+
// RUN: %clang_cc1 -std=c++20 %t/C.cppm -emit-reduced-module-interface -o %t/C.v1.pcm \
47+
// RUN: -fmodule-file=m=%t/m.v1.pcm -fmodule-file=m:partA=%t/m-partA.v1.pcm \
48+
// RUN: -fmodule-file=m:partB=%t/m-partB.pcm -fmodule-file=Common=%t/Common.pcm
49+
// RUN: diff %t/C.pcm %t/C.v1.pcm &> /dev/null
50+
51+
//--- Common.cppm
52+
export module Common;
53+
54+
export namespace N {
55+
struct A {
56+
constexpr operator int() {
57+
return 43;
58+
}
59+
};
60+
}
61+
62+
//--- m-partA.cppm
63+
export module m:partA;
64+
import Common;
65+
66+
export namespace N {}
67+
68+
//--- m-partA.v1.cppm
69+
export module m:partA;
70+
import Common;
71+
72+
export namespace N {
73+
constexpr bool adl(A) { return true; }
74+
}
75+
76+
//--- m-partB.cppm
77+
export module m:partB;
78+
79+
export constexpr bool adl(int) { return false; }
80+
81+
//--- m.cppm
82+
export module m;
83+
export import :partA;
84+
export import :partB;
85+
86+
//--- B.cppm
87+
export module B;
88+
import m;
89+
90+
export template <class C>
91+
constexpr bool test_adl(C c) {
92+
return adl(c);
93+
}
94+
95+
//--- use.cpp
96+
// expected-no-diagnostics
97+
import B;
98+
import Common;
99+
100+
void test() {
101+
N::A a;
102+
static_assert(test_adl(a) == EXPECTED_VALUE);
103+
}
104+
105+
//--- C.cppm
106+
export module B;
107+
import m;
108+
109+
export template <class C>
110+
constexpr bool not_test_adl(C c) {
111+
return false;
112+
}

0 commit comments

Comments
 (0)