Skip to content

Commit b5a0a4e

Browse files
committed
added more tests
1 parent 23fc3c2 commit b5a0a4e

File tree

3 files changed

+92
-33
lines changed

3 files changed

+92
-33
lines changed

lib/ClangImporter/ImportDecl.cpp

Lines changed: 13 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1501,27 +1501,19 @@ namespace {
15011501
// or the original C type.
15021502
clang::QualType ClangType = Decl->getUnderlyingType();
15031503

1504-
clang::QualType checkType = ClangType;
1505-
if (auto elaborated =
1506-
dyn_cast<clang::ElaboratedType>(checkType.getTypePtr())) {
1507-
checkType = elaborated->getNamedType();
1508-
}
1509-
1510-
if (auto templateSpec = dyn_cast<clang::TemplateSpecializationType>(
1511-
checkType.getTypePtr())) {
1512-
checkType = templateSpec->desugar();
1513-
}
1514-
1515-
if (auto recordType = checkType->getAs<clang::RecordType>()) {
1516-
if (auto spec = dyn_cast<clang::ClassTemplateSpecializationDecl>(
1517-
recordType->getDecl())) {
1518-
if (spec->getSpecializationKind() ==
1519-
clang::TSK_ExplicitSpecialization &&
1520-
!spec->isCompleteDefinition()) {
1521-
Impl.addImportDiagnostic(
1522-
Decl, Diagnostic(diag::record_is_dependent, Decl->getName()),
1523-
Decl->getLocation());
1524-
return nullptr;
1504+
// Prevent import of typedefs to forward-declared explicit template
1505+
// specializations, which would trigger assertion in Clang.
1506+
if (auto *templateSpec = dyn_cast<clang::TemplateSpecializationType>(
1507+
importer::desugarIfElaborated(ClangType).getTypePtr())) {
1508+
if (auto *recordType =
1509+
templateSpec->desugar()->getAs<clang::RecordType>()) {
1510+
if (auto *spec = dyn_cast<clang::ClassTemplateSpecializationDecl>(
1511+
recordType->getDecl())) {
1512+
if (spec->getSpecializationKind() ==
1513+
clang::TSK_ExplicitSpecialization &&
1514+
!spec->isCompleteDefinition()) {
1515+
return nullptr;
1516+
}
15251517
}
15261518
}
15271519
}
Lines changed: 54 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,63 @@
11
#ifndef FORWARD_DECLARED_SPECIALIZATION_H
22
#define FORWARD_DECLARED_SPECIALIZATION_H
33

4-
template <typename T>
5-
struct MyTemplate {
6-
T value;
4+
// Basic template definition
5+
template <typename T>
6+
struct BasicTemplate {
7+
T value;
78
};
89

9-
template <>
10-
struct MyTemplate<int>;
11-
typedef MyTemplate<int> MyIntTemplate;
10+
// Case 1: Forward-declared specialization (should NOT import)
11+
template <>
12+
struct BasicTemplate<int>;
13+
typedef BasicTemplate<int> ForwardDeclaredInt;
1214

13-
template <>
14-
struct MyTemplate<double> {
15+
// Case 2: Complete specialization (should import successfully)
16+
template <>
17+
struct BasicTemplate<double> {
1518
double value;
19+
double getValue() const { return value; }
1620
};
17-
typedef MyTemplate<double> MyCompleteIntTemplate;
21+
typedef BasicTemplate<double> CompleteDouble;
1822

19-
#endif // FORWARD_DECLARED_SPECIALIZATION_H
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/forward-declared-specialization.swift

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,31 @@
22

33
import ForwardDeclaredSpecialization
44

5-
func testForwardDeclaredSpecialization(_ param: MyIntTemplate) { // expected-error {{cannot find type 'MyIntTemplate' in scope}}
5+
func testForwardDeclaredSpecialization(_ param: ForwardDeclaredInt) {
6+
// expected-error@-1 {{cannot find type 'ForwardDeclaredInt' in scope}}
67
}
78

8-
func testCompleteSpecialization(_ param: MyCompleteIntTemplate) {
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
932
}

0 commit comments

Comments
 (0)