Skip to content

Commit 0d490ae

Browse files
authored
[clang] fix definition data not being propagated to all redecls (#157019)
This fixes the workaround added in 8a63989, so that when a fake definition data is corrected, all redeclarations are also updated to point to it. Since this regression was never released, there are no release notes. Fixes #154840
1 parent 4f1b98b commit 0d490ae

File tree

2 files changed

+99
-0
lines changed

2 files changed

+99
-0
lines changed

clang/lib/Serialization/ASTReaderDecl.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2107,6 +2107,8 @@ void ASTDeclMerger::MergeDefinitionData(
21072107
auto *Def = DD.Definition;
21082108
DD = std::move(MergeDD);
21092109
DD.Definition = Def;
2110+
while ((Def = Def->getPreviousDecl()))
2111+
cast<CXXRecordDecl>(Def)->DefinitionData = &DD;
21102112
return;
21112113
}
21122114

clang/test/Modules/GH154840.cpp

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
// RUN: rm -rf %t
2+
// RUN: mkdir -p %t
3+
// RUN: split-file %s %t
4+
// RUN: cd %t
5+
//
6+
// RUN: %clang_cc1 -fmodule-name=A -fno-cxx-modules -emit-module -fmodules -xc++ A.cppmap -o A.pcm
7+
// RUN: %clang_cc1 -fmodule-name=B -fno-cxx-modules -emit-module -fmodules -xc++ B.cppmap -o B.pcm -fmodule-file=A.pcm
8+
// RUN: %clang_cc1 -fmodule-name=C -fno-cxx-modules -emit-module -fmodules -xc++ C.cppmap -o C.pcm -fmodule-file=A.pcm
9+
// RUN: %clang_cc1 -fmodule-name=D -fno-cxx-modules -emit-module -fmodules -xc++ D.cppmap -o D.pcm -fmodule-file=A.pcm
10+
// RUN: %clang_cc1 -fmodule-name=E -fno-cxx-modules -emit-module -fmodules -xc++ E.cppmap -o E.pcm -fmodule-file=D.pcm -fmodule-file=B.pcm -fmodule-file=C.pcm
11+
// RUN: %clang_cc1 -fno-cxx-modules -fmodules -fmodule-file=B.pcm -fmodule-file=E.pcm -emit-llvm -o /dev/null S.cpp
12+
13+
//--- A.h
14+
namespace std {
15+
16+
template <class T> void zz(T);
17+
18+
template <class> struct vec {
19+
struct w {};
20+
struct xx {};
21+
22+
vec(vec &) { init(); }
23+
constexpr vec &operator=(const vec &);
24+
template <class U> constexpr void pb(U);
25+
constexpr void init();
26+
27+
w s;
28+
};
29+
30+
template <class T> constexpr void vec<T>::init() {
31+
xx yy;
32+
zz(yy);
33+
}
34+
35+
template <class T> constexpr vec<T> &vec<T>::operator=(const vec &) {
36+
pb(s);
37+
return *this;
38+
}
39+
40+
template <class T> template <class U> constexpr void vec<T>::pb(U) { init(); }
41+
} // namespace std
42+
43+
//--- A.cppmap
44+
module "A" {
45+
header "A.h"
46+
}
47+
48+
//--- X.h
49+
#pragma clang module import A
50+
51+
namespace project {
52+
class thing : std::vec<thing> {};
53+
} // namespace project
54+
55+
//--- B.h
56+
#include "X.h"
57+
58+
//--- B.cppmap
59+
module "B" {
60+
header "B.h"
61+
}
62+
63+
//--- C.h
64+
#include "X.h"
65+
66+
//--- C.cppmap
67+
module "C" {
68+
header "C.h"
69+
}
70+
71+
//--- D.h
72+
#include "X.h"
73+
74+
//--- D.cppmap
75+
module "D" {
76+
header "D.h"
77+
}
78+
79+
//--- Y.h
80+
#include "X.h"
81+
struct other {
82+
other() : data(data) {}
83+
std::vec<project::thing> data;
84+
};
85+
86+
//--- E.h
87+
#include "Y.h"
88+
89+
//--- E.cppmap
90+
module "E" {
91+
header "E.h"
92+
}
93+
94+
//--- S.cpp
95+
#pragma clang module import A
96+
#pragma clang module import E
97+
void func(std::vec<project::thing> *a, std::vec<project::thing> *b) { *a = *b; }

0 commit comments

Comments
 (0)