mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
[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.
This commit is contained in:
@@ -1501,23 +1501,6 @@ namespace {
|
||||
// or the original C type.
|
||||
clang::QualType ClangType = Decl->getUnderlyingType();
|
||||
|
||||
// Prevent import of typedefs to forward-declared explicit template
|
||||
// specializations, which would trigger assertion in Clang.
|
||||
if (auto *templateSpec = dyn_cast<clang::TemplateSpecializationType>(
|
||||
importer::desugarIfElaborated(ClangType).getTypePtr())) {
|
||||
if (auto *recordType =
|
||||
templateSpec->desugar()->getAs<clang::RecordType>()) {
|
||||
if (auto *spec = dyn_cast<clang::ClassTemplateSpecializationDecl>(
|
||||
recordType->getDecl())) {
|
||||
if (spec->getSpecializationKind() ==
|
||||
clang::TSK_ExplicitSpecialization &&
|
||||
!spec->isCompleteDefinition()) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SwiftType = Impl.importTypeIgnoreIUO(
|
||||
ClangType, ImportTypeKind::Typedef,
|
||||
ImportDiagnosticAdder(Impl, Decl, Decl->getLocation()),
|
||||
@@ -3346,6 +3329,15 @@ namespace {
|
||||
decl->getName() == "_Expr" || decl->getName() == "__val_expr"))
|
||||
return nullptr;
|
||||
|
||||
// Don't even try to specialize/import this template if it's
|
||||
// a forward-declared specialization like this:
|
||||
//
|
||||
// template <> struct MyTemplate<int>;
|
||||
//
|
||||
if (decl->getSpecializationKind() == clang::TSK_ExplicitSpecialization &&
|
||||
!decl->isCompleteDefinition())
|
||||
return nullptr;
|
||||
|
||||
// `decl->getDefinition()` can return nullptr before the call to sema and
|
||||
// return its definition afterwards.
|
||||
clang::Sema &clangSema = Impl.getClangSema();
|
||||
|
||||
@@ -60,4 +60,11 @@ struct PartialTemplate<T*, double> {
|
||||
};
|
||||
typedef PartialTemplate<int*, double> CompletePartial;
|
||||
|
||||
// Some functions that use forward-declared specializations
|
||||
void TakesIncompleteSpecialization(BasicTemplate<int>);
|
||||
BasicTemplate<int> ReturnsIncompleteSpecialization();
|
||||
|
||||
void TakesPtrToIncompleteSpecialization(BasicTemplate<int> *);
|
||||
BasicTemplate<int> *ReturnsPtrToIncompleteSpecialization();
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// RUN: %target-typecheck-verify-swift -I %S/Inputs -cxx-interoperability-mode=default
|
||||
// RUN: %target-typecheck-verify-swift -I %S/Inputs -cxx-interoperability-mode=default -suppress-remarks -suppress-notes
|
||||
|
||||
import ForwardDeclaredSpecialization
|
||||
|
||||
@@ -30,3 +30,17 @@ func testCompletePartial(_ param: CompletePartial) {
|
||||
let _ = param.ptr
|
||||
let _ = param.value
|
||||
}
|
||||
|
||||
func testFunctionsUsingIncompleteSpec() {
|
||||
let inc = ReturnsIncompleteSpecialization()
|
||||
// expected-error@-1 {{return type is unavailable in Swift}}
|
||||
// expected-warning@-2 {{constant 'inc' inferred to have type 'Never', which is an enum with no cases}}
|
||||
TakesIncompleteSpecialization(inc)
|
||||
// expected-error@-1 {{cannot find 'TakesIncompleteSpecialization' in scope}}
|
||||
}
|
||||
|
||||
func testFunctionsUsingPtrToIncompleteSpec(_ ptr: OpaquePointer) {
|
||||
let incPtr = ReturnsPtrToIncompleteSpecialization()
|
||||
TakesPtrToIncompleteSpecialization(incPtr)
|
||||
TakesPtrToIncompleteSpecialization(ptr)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user