[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:
Jordan Rose
2014-05-01 20:40:06 +00:00
parent 3f77c807b1
commit 92bcd97d54
2 changed files with 44 additions and 10 deletions

View File

@@ -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));