Skip to content

Commit b5a3eee

Browse files
committed
Merge remote-tracking branch 'origin/main' into rebranch
2 parents 5dd12a7 + cc8f060 commit b5a3eee

File tree

4 files changed

+118
-0
lines changed

4 files changed

+118
-0
lines changed

lib/ClangImporter/ImportDecl.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1498,6 +1498,24 @@ namespace {
14981498
// bridging, i.e. if the imported typealias should name a bridged type
14991499
// or the original C type.
15001500
clang::QualType ClangType = Decl->getUnderlyingType();
1501+
1502+
// Prevent import of typedefs to forward-declared explicit template
1503+
// specializations, which would trigger assertion in Clang.
1504+
if (auto *templateSpec = dyn_cast<clang::TemplateSpecializationType>(
1505+
importer::desugarIfElaborated(ClangType).getTypePtr())) {
1506+
if (auto *recordType =
1507+
templateSpec->desugar()->getAs<clang::RecordType>()) {
1508+
if (auto *spec = dyn_cast<clang::ClassTemplateSpecializationDecl>(
1509+
recordType->getDecl())) {
1510+
if (spec->getSpecializationKind() ==
1511+
clang::TSK_ExplicitSpecialization &&
1512+
!spec->isCompleteDefinition()) {
1513+
return nullptr;
1514+
}
1515+
}
1516+
}
1517+
}
1518+
15011519
SwiftType = Impl.importTypeIgnoreIUO(
15021520
ClangType, ImportTypeKind::Typedef,
15031521
ImportDiagnosticAdder(Impl, Decl, Decl->getLocation()),
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
#ifndef FORWARD_DECLARED_SPECIALIZATION_H
2+
#define FORWARD_DECLARED_SPECIALIZATION_H
3+
4+
// Basic template definition
5+
template <typename T>
6+
struct BasicTemplate {
7+
T value;
8+
};
9+
10+
// Case 1: Forward-declared specialization (should NOT import)
11+
template <>
12+
struct BasicTemplate<int>;
13+
typedef BasicTemplate<int> ForwardDeclaredInt;
14+
15+
// Case 2: Complete specialization (should import successfully)
16+
template <>
17+
struct BasicTemplate<double> {
18+
double value;
19+
double getValue() const { return value; }
20+
};
21+
typedef BasicTemplate<double> CompleteDouble;
22+
23+
// Case 3: Specialization defined after typedef (should import)
24+
template <>
25+
struct BasicTemplate<float>;
26+
typedef BasicTemplate<float> FloatTypedef;
27+
28+
template <>
29+
struct BasicTemplate<float> {
30+
float value;
31+
};
32+
33+
// Case 4: For comparison - forward-declared non-templated struct (have same behavior)
34+
struct ForwardDeclaredStruct;
35+
typedef ForwardDeclaredStruct ForwardDeclaredStructType;
36+
37+
// Case 5: Complete non-templated struct (imports successfully)
38+
struct CompleteStruct {
39+
int value;
40+
};
41+
typedef CompleteStruct CompleteStructType;
42+
43+
// Template for partial specialization test
44+
template <typename T, typename U>
45+
struct PartialTemplate {
46+
T first;
47+
U second;
48+
};
49+
50+
// Case 6: Forward-declared partial specialization (should NOT import - same as explicit)
51+
template <typename T>
52+
struct PartialTemplate<T*, int>; // Forward declaration only
53+
typedef PartialTemplate<double*, int> ForwardDeclaredPartial;
54+
55+
// Case 7: Complete partial specialization (should import successfully)
56+
template <typename T>
57+
struct PartialTemplate<T*, double> {
58+
T* ptr;
59+
double value;
60+
};
61+
typedef PartialTemplate<int*, double> CompletePartial;
62+
63+
#endif

test/Interop/Cxx/templates/Inputs/module.modulemap

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,3 +182,8 @@ module VariableTemplate {
182182
header "variable-template.h"
183183
requires cplusplus
184184
}
185+
186+
module ForwardDeclaredSpecialization {
187+
header "ForwardDeclaredSpecialization.h"
188+
requires cplusplus
189+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// RUN: %target-typecheck-verify-swift -I %S/Inputs -cxx-interoperability-mode=default
2+
3+
import ForwardDeclaredSpecialization
4+
5+
func testForwardDeclaredSpecialization(_ param: ForwardDeclaredInt) {
6+
// expected-error@-1 {{cannot find type 'ForwardDeclaredInt' in scope}}
7+
}
8+
9+
func testCompleteSpecialization(_ param: CompleteDouble) {
10+
let _ = param.getValue()
11+
}
12+
13+
func testSpecializationDefinedAfter(_ param: FloatTypedef) {
14+
let _ = param.value
15+
}
16+
17+
func testForwardDeclaredStruct(_ param: ForwardDeclaredStructType) {
18+
// expected-error@-1 {{cannot find type 'ForwardDeclaredStructType' in scope}}
19+
}
20+
21+
func testCompleteStruct(_ param: CompleteStructType) {
22+
let _ = param.value
23+
}
24+
25+
func testForwardDeclaredPartial(_ param: ForwardDeclaredPartial) {
26+
// expected-error@-1 {{cannot find type 'ForwardDeclaredPartial' in scope}}
27+
}
28+
29+
func testCompletePartial(_ param: CompletePartial) {
30+
let _ = param.ptr
31+
let _ = param.value
32+
}

0 commit comments

Comments
 (0)