Skip to content

Commit 0e6bb8a

Browse files
committed
[clang] fix redecl chain assumption when checking liknkage consistency
In C++, it can be assumed the same linkage will be computed for all redeclarations of an entity, and we have assertions to check this. However, the linkage for a declaration can be requested in the middle of deserealization, and at this point the redecl chain is not well formed, as computation of the most recent declaration is deferred. This patch makes that assertion work even in such conditions. This fixes a regression introduced in #152845, which was never released, so there are no release notes for this. Fixes 153933
1 parent 1d73b2c commit 0e6bb8a

File tree

2 files changed

+32
-7
lines changed

2 files changed

+32
-7
lines changed

clang/lib/AST/Decl.cpp

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1604,17 +1604,20 @@ LinkageInfo LinkageComputer::getLVForDecl(const NamedDecl *D,
16041604
// We have just computed the linkage for this decl. By induction we know
16051605
// that all other computed linkages match, check that the one we just
16061606
// computed also does.
1607-
NamedDecl *Old = nullptr;
1608-
for (auto *I : D->redecls()) {
1609-
auto *T = cast<NamedDecl>(I);
1610-
if (T == D)
1607+
// We can't assume the redecl chain is well formed at this point,
1608+
// so keep track of already visited declarations.
1609+
for (llvm::SmallPtrSet<const Decl *, 4> AlreadyVisited{D}; /**/; /**/) {
1610+
D = cast<NamedDecl>(const_cast<NamedDecl *>(D)->getNextRedeclarationImpl());
1611+
if (!AlreadyVisited.insert(D).second)
1612+
break;
1613+
if (D->isInvalidDecl())
16111614
continue;
1612-
if (!T->isInvalidDecl() && T->hasCachedLinkage()) {
1613-
Old = T;
1615+
if (auto OldLinkage = D->getCachedLinkage();
1616+
OldLinkage != Linkage::Invalid) {
1617+
assert(LV.getLinkage() == OldLinkage);
16141618
break;
16151619
}
16161620
}
1617-
assert(!Old || Old->getCachedLinkage() == D->getCachedLinkage());
16181621
#endif
16191622

16201623
return LV;

clang/test/Modules/GH153933.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// RUN: rm -rf %t
2+
// RUN: mkdir -p %t
3+
// RUN: split-file %s %t
4+
//
5+
// RUN: %clang_cc1 -std=c++20 %t/B.cppm -emit-module-interface -o %t/B.pcm
6+
// RUN: %clang_cc1 -std=c++20 -fsyntax-only -fprebuilt-module-path=%t %t/C.cpp
7+
8+
//--- A.hpp
9+
template<class> struct A {};
10+
template<class T> struct B {
11+
virtual A<T> v() { return {}; }
12+
};
13+
B<void> x;
14+
15+
//--- B.cppm
16+
module;
17+
#include "A.hpp"
18+
export module B;
19+
20+
//--- C.cpp
21+
#include "A.hpp"
22+
import B;

0 commit comments

Comments
 (0)