From b1aff68da99cec130fee362aa045bc9ea5cdd8dc Mon Sep 17 00:00:00 2001 From: Joe Groff Date: Sat, 15 Jun 2013 00:41:32 +0000 Subject: [PATCH] Allow [class_protocol] protocols to be [objc]. Swift SVN r5591 --- include/swift/AST/Diagnostics.def | 2 ++ lib/IRGen/GenProto.cpp | 1 + lib/Sema/TypeCheckDecl.cpp | 36 +++++++++++++++++++++++++------ 3 files changed, 32 insertions(+), 7 deletions(-) diff --git a/include/swift/AST/Diagnostics.def b/include/swift/AST/Diagnostics.def index ff178f7ffab..02684b4ec34 100644 --- a/include/swift/AST/Diagnostics.def +++ b/include/swift/AST/Diagnostics.def @@ -1023,6 +1023,8 @@ ERROR(conversion_params,sema_tcd,none, "conversion function %0 has non-defaulted parameters", (Identifier)) ERROR(invalid_objc_decl,sema_tcd,none, "only classes and their methods can be declared 'objc'", ()) +ERROR(objc_protocol_not_class_protocol,sema_tcd,none, + "only [class_protocol] protocols can be declared 'objc'", ()) ERROR(invalid_iboutlet,sema_tcd,none, "only properties can be declared 'iboutlet'", ()) ERROR(invalid_ibaction_decl,sema_tcd,none, diff --git a/lib/IRGen/GenProto.cpp b/lib/IRGen/GenProto.cpp index a3cb773f718..76d37ffcbce 100644 --- a/lib/IRGen/GenProto.cpp +++ b/lib/IRGen/GenProto.cpp @@ -1546,6 +1546,7 @@ static void buildValueWitnessFunction(IRGenModule &IGM, = emitTypeMetadataRefForClassBoundedExistential(IGF, existential, concreteType); IGF.Builder.CreateRet(result); + } else { llvm::Value *result = emitTypeMetadataRefForOpaqueExistential(IGF, obj, concreteType); diff --git a/lib/Sema/TypeCheckDecl.cpp b/lib/Sema/TypeCheckDecl.cpp index d0c1c10d426..56e7d52df92 100644 --- a/lib/Sema/TypeCheckDecl.cpp +++ b/lib/Sema/TypeCheckDecl.cpp @@ -461,6 +461,20 @@ public: void visitProtocolDecl(ProtocolDecl *PD) { if (IsSecondPass) return; + + // The protocol requires ObjC interop if the protocol or any of the + // protocols it refines are [objc]. + if (PD->getAttrs().isObjC()) + PD->setIsObjC(true); + else { + PD->setIsObjC(false); + for (auto *parent : PD->getProtocols()) { + if (parent->isObjC()) { + PD->setIsObjC(true); + break; + } + } + } // Fix the 'This' associated type. TypeAliasDecl *thisDecl = nullptr; @@ -1116,17 +1130,25 @@ void DeclChecker::validateAttributes(ValueDecl *VD) { }; if (Attrs.isObjC()) { - // Only classes, instance properties, and methods can be ObjC. - bool isLegal = false; + // Only classes, class protocols, instance properties, and methods can be + // ObjC. + Optional> error; if (isa(VD)) { - isLegal = true; + /* ok */ } else if (isa(VD) && isInClassContext(VD)) { - isLegal = !isOperator; + if (isOperator) + error = diag::invalid_objc_decl; } else if (isa(VD) && isInClassContext(VD)) { - isLegal = true; + /* ok */ + } else if (auto *protocol = dyn_cast(VD)) { + if (!protocol->isClassBounded()) + error = diag::objc_protocol_not_class_protocol; + } else { + error = diag::invalid_objc_decl; } - if (!isLegal) { - TC.diagnose(VD->getStartLoc(), diag::invalid_objc_decl); + + if (error) { + TC.diagnose(VD->getStartLoc(), *error); VD->getMutableAttrs().ObjC = false; return; }