Skip to content

Commit bb5bb97

Browse files
committed
[cxx-interop] Move incomplete template specialization check
We were only previously doing this check when we had a typedef, because that is the scenario where we encountered this issue. This patch moves the check closer to where we would actually instantiate the template, so that these cases can be stopped in more situations.
1 parent ef9e3ef commit bb5bb97

File tree

3 files changed

+31
-18
lines changed

3 files changed

+31
-18
lines changed

lib/ClangImporter/ImportDecl.cpp

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

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-
}
1517-
}
1518-
}
1519-
}
1520-
15211504
SwiftType = Impl.importTypeIgnoreIUO(
15221505
ClangType, ImportTypeKind::Typedef,
15231506
ImportDiagnosticAdder(Impl, Decl, Decl->getLocation()),
@@ -3346,6 +3329,15 @@ namespace {
33463329
decl->getName() == "_Expr" || decl->getName() == "__val_expr"))
33473330
return nullptr;
33483331

3332+
// Don't even try to specialize/import this template if it's
3333+
// a forward-declared specialization like this:
3334+
//
3335+
// template <> struct MyTemplate<int>;
3336+
//
3337+
if (decl->getSpecializationKind() == clang::TSK_ExplicitSpecialization &&
3338+
!decl->isCompleteDefinition())
3339+
return nullptr;
3340+
33493341
// `decl->getDefinition()` can return nullptr before the call to sema and
33503342
// return its definition afterwards.
33513343
clang::Sema &clangSema = Impl.getClangSema();

test/Interop/Cxx/templates/Inputs/ForwardDeclaredSpecialization.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,4 +60,11 @@ struct PartialTemplate<T*, double> {
6060
};
6161
typedef PartialTemplate<int*, double> CompletePartial;
6262

63+
// Some functions that use forward-declared specializations
64+
void TakesIncompleteSpecialization(BasicTemplate<int>);
65+
BasicTemplate<int> ReturnsIncompleteSpecialization();
66+
67+
void TakesPtrToIncompleteSpecialization(BasicTemplate<int> *);
68+
BasicTemplate<int> *ReturnsPtrToIncompleteSpecialization();
69+
6370
#endif

test/Interop/Cxx/templates/forward-declared-specialization.swift

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %target-typecheck-verify-swift -I %S/Inputs -cxx-interoperability-mode=default
1+
// RUN: %target-typecheck-verify-swift -I %S/Inputs -cxx-interoperability-mode=default -suppress-remarks -suppress-notes
22

33
import ForwardDeclaredSpecialization
44

@@ -30,3 +30,17 @@ func testCompletePartial(_ param: CompletePartial) {
3030
let _ = param.ptr
3131
let _ = param.value
3232
}
33+
34+
func testFunctionsUsingIncompleteSpec() {
35+
let inc = ReturnsIncompleteSpecialization()
36+
// expected-error@-1 {{return type is unavailable in Swift}}
37+
// expected-warning@-2 {{constant 'inc' inferred to have type 'Never', which is an enum with no cases}}
38+
TakesIncompleteSpecialization(inc)
39+
// expected-error@-1 {{cannot find 'TakesIncompleteSpecialization' in scope}}
40+
}
41+
42+
func testFunctionsUsingPtrToIncompleteSpec(_ ptr: OpaquePointer) {
43+
let incPtr = ReturnsPtrToIncompleteSpecialization()
44+
TakesPtrToIncompleteSpecialization(incPtr)
45+
TakesPtrToIncompleteSpecialization(ptr)
46+
}

0 commit comments

Comments
 (0)