mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
[ClangImporter] Don't crash if we have a SWIFT_CLASS but the module is missing.
Also, if the generated header says that a class or protocol is available in a module, but we can't find it, we should treat the decl as missing rather than pretending it's a normal Objective-C decl. Part of <rdar://problem/16776466> Swift SVN r17175
This commit is contained in:
@@ -3344,18 +3344,38 @@ namespace {
|
||||
}
|
||||
|
||||
template <typename T, typename U>
|
||||
T *resolveSwiftDeclIfAnnotated(const U *decl, Identifier name,
|
||||
const DeclContext *dc) {
|
||||
bool hasNativeSwiftDecl(const U *decl, Identifier name,
|
||||
const DeclContext *dc, T *&swiftDecl) {
|
||||
using clang::AnnotateAttr;
|
||||
for (auto annotation : decl->template specific_attrs<AnnotateAttr>()) {
|
||||
if (annotation->getAnnotation() == SWIFT_NATIVE_ANNOTATION_STRING) {
|
||||
auto wrapperUnit = cast<ClangModuleUnit>(dc->getModuleScopeContext());
|
||||
return resolveSwiftDecl<T>(decl, name,
|
||||
wrapperUnit->getAdapterModule());
|
||||
if (auto adapter = wrapperUnit->getAdapterModule()) {
|
||||
swiftDecl = resolveSwiftDecl<T>(decl, name, adapter);
|
||||
} else {
|
||||
// This is intended to have a Swift decl, but the Swift part is
|
||||
// missing. Fail instead of pretending it's a normal ObjC decl.
|
||||
swiftDecl = nullptr;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
void markMissingSwiftDecl(ValueDecl *VD) {
|
||||
const char *message;
|
||||
if (isa<ClassDecl>(VD))
|
||||
message = "cannot find Swift declaration for this class";
|
||||
else if (isa<ProtocolDecl>(VD))
|
||||
message = "cannot find Swift declaration for this protocol";
|
||||
else
|
||||
llvm_unreachable("unknown bridged decl kind");
|
||||
auto attr = AvailabilityAttr::createImplicitUnavailableAttr(
|
||||
Impl.SwiftContext, message);
|
||||
VD->getMutableAttrs().add(attr);
|
||||
}
|
||||
|
||||
Decl *VisitObjCProtocolDecl(const clang::ObjCProtocolDecl *decl) {
|
||||
@@ -3396,9 +3416,10 @@ namespace {
|
||||
if (!dc)
|
||||
return nullptr;
|
||||
|
||||
if (auto native = resolveSwiftDeclIfAnnotated<ProtocolDecl>(decl, name,
|
||||
dc))
|
||||
return native;
|
||||
ProtocolDecl *nativeDecl;
|
||||
bool declaredNative = hasNativeSwiftDecl(decl, name, dc, nativeDecl);
|
||||
if (declaredNative && nativeDecl)
|
||||
return nativeDecl;
|
||||
|
||||
// Create the protocol declaration and record it.
|
||||
auto result = Impl.createDeclWithClangNode<ProtocolDecl>(decl,
|
||||
@@ -3410,6 +3431,9 @@ namespace {
|
||||
result->computeType();
|
||||
addObjCAttribute(result, ObjCSelector(Impl.SwiftContext, 0, origName));
|
||||
|
||||
if (declaredNative)
|
||||
markMissingSwiftDecl(result);
|
||||
|
||||
Impl.ImportedDecls[decl->getCanonicalDecl()] = result;
|
||||
|
||||
// Create the archetype for the implicit 'Self'.
|
||||
@@ -3544,8 +3568,10 @@ namespace {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (auto native = resolveSwiftDeclIfAnnotated<ClassDecl>(decl, name, dc))
|
||||
return native;
|
||||
ClassDecl *nativeDecl;
|
||||
bool declaredNative = hasNativeSwiftDecl(decl, name, dc, nativeDecl);
|
||||
if (declaredNative && nativeDecl)
|
||||
return nativeDecl;
|
||||
|
||||
// Create the class declaration and record it.
|
||||
auto result = Impl.createDeclWithClangNode<ClassDecl>(decl,
|
||||
@@ -3559,6 +3585,9 @@ namespace {
|
||||
result->setAddedImplicitInitializers();
|
||||
addObjCAttribute(result, ObjCSelector(Impl.SwiftContext, 0, name));
|
||||
|
||||
if (declaredNative)
|
||||
markMissingSwiftDecl(result);
|
||||
|
||||
// If this Objective-C class has a supertype, import it.
|
||||
if (auto objcSuper = decl->getSuperClass()) {
|
||||
auto super = cast_or_null<ClassDecl>(Impl.importDecl(objcSuper));
|
||||
|
||||
Reference in New Issue
Block a user