Allow [class_protocol] protocols to be [objc].

Swift SVN r5591
This commit is contained in:
Joe Groff
2013-06-15 00:41:32 +00:00
parent 491de4fc55
commit b1aff68da9
3 changed files with 32 additions and 7 deletions

View File

@@ -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,

View File

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

View File

@@ -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<Diag<>> error;
if (isa<ClassDecl>(VD)) {
isLegal = true;
/* ok */
} else if (isa<FuncDecl>(VD) && isInClassContext(VD)) {
isLegal = !isOperator;
if (isOperator)
error = diag::invalid_objc_decl;
} else if (isa<VarDecl>(VD) && isInClassContext(VD)) {
isLegal = true;
/* ok */
} else if (auto *protocol = dyn_cast<ProtocolDecl>(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;
}