Skip to content

Commit 8a3fe30

Browse files
authored
[PATCH] [clang][frontend] Fix serialization for CXXConstructorDecl (refs #132794) (#133077)
When retrieving the ExplicitSpecifier from a CXXConstructorDecl, one of its canonical declarations is returned. To correctly write the declaration record the ExplicitSpecifier of the current declaration must be used. Failing to do so results in a crash during deserialization.
1 parent 7d86904 commit 8a3fe30

File tree

3 files changed

+47
-1
lines changed

3 files changed

+47
-1
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,7 @@ Bug Fixes in This Version
323323
- Fixed a modules crash where exception specifications were not propagated properly (#GH121245, relanded in #GH129982)
324324
- Fixed a problematic case with recursive deserialization within ``FinishedDeserializing()`` where
325325
``PassInterestingDeclsToConsumer()`` was called before the declarations were safe to be passed. (#GH129982)
326+
- Fixed a modules crash where an explicit Constructor was deserialized. (#GH132794)
326327

327328
Bug Fixes to Compiler Builtins
328329
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

clang/lib/Serialization/ASTWriterDecl.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1726,7 +1726,7 @@ void ASTDeclWriter::VisitCXXConstructorDecl(CXXConstructorDecl *D) {
17261726
"CXXConstructorDeclBits");
17271727

17281728
Record.push_back(D->getTrailingAllocKind());
1729-
addExplicitSpecifier(D->getExplicitSpecifier(), Record);
1729+
addExplicitSpecifier(D->getExplicitSpecifierInternal(), Record);
17301730
if (auto Inherited = D->getInheritedConstructor()) {
17311731
Record.AddDeclRef(Inherited.getShadowDecl());
17321732
Record.AddDeclRef(Inherited.getConstructor());
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// Tests complex explicit constructor across modules.
2+
//
3+
// RUN: rm -rf %t
4+
// RUN: mkdir -p %t
5+
// RUN: split-file %s %t
6+
7+
// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/Foo.cppm \
8+
// RUN: -o %t/Foo.pcm
9+
10+
// RUN: %clang_cc1 -std=c++20 -emit-module-interface \
11+
// RUN: -fmodule-file=Foo=%t/Foo.pcm \
12+
// RUN: %t/Bar.cppm \
13+
// RUN: -o %t/Bar.pcm
14+
15+
// RUN: %clang_cc1 -std=c++20 -emit-obj \
16+
// RUN: -main-file-name Bar.cppm \
17+
// RUN: -fmodule-file=Foo=%t/Foo.pcm \
18+
// RUN: -x pcm %t/Bar.pcm \
19+
// RUN: -o %t/Bar.o
20+
21+
//--- Foo.cppm
22+
export module Foo;
23+
24+
export {
25+
template<class T>
26+
class Foo {
27+
public:
28+
template<class... Args>
29+
explicit (sizeof...(Args) == 1) Foo(Args&&... args);
30+
};
31+
}
32+
33+
template<class T>
34+
template<class... Args>
35+
inline Foo<T>::Foo(Args&&... args) {}
36+
37+
//--- Bar.cppm
38+
export module Bar;
39+
import Foo;
40+
41+
struct Bar {};
42+
43+
void a() {
44+
auto foo = Foo<Bar>{};
45+
}

0 commit comments

Comments
 (0)