From: Fariborz Jahanian Date: Mon, 17 Sep 2007 21:07:36 +0000 (+0000) Subject: Patch to add objective-c's @protocl type declaration. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=25e077d59a8e8e43b65882b69610a3d5e2aaf53c;p=clang Patch to add objective-c's @protocl type declaration. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@42060 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/AST/Decl.cpp b/AST/Decl.cpp index d45780043f..8208c02049 100644 --- a/AST/Decl.cpp +++ b/AST/Decl.cpp @@ -289,3 +289,23 @@ void ObjcInterfaceDecl::ObjcAddMethods(ObjcMethodDecl **insMethods, } } +/// ObjcAddProtoMethods - Insert instance and methods declarations into +/// ObjcProtocolDecl's ProtoInsMethods and ProtoClsMethods fields. +/// +void ObjcProtocolDecl::ObjcAddProtoMethods(ObjcMethodDecl **insMethods, + unsigned numInsMembers, + ObjcMethodDecl **clsMethods, + unsigned numClsMembers) { + NumProtoInsMethods = numInsMembers; + if (numInsMembers) { + ProtoInsMethods = new ObjcProtoMethodDecl*[numInsMembers]; + memcpy(ProtoInsMethods, insMethods, numInsMembers*sizeof(ObjcMethodDecl*)); + } + NumProtoClsMethods = numClsMembers; + if (numClsMembers) { + ProtoClsMethods = new ObjcProtoMethodDecl*[numClsMembers]; + memcpy(ProtoClsMethods, clsMethods, numClsMembers*sizeof(ObjcMethodDecl*)); + } +} + + diff --git a/Parse/MinimalAction.cpp b/Parse/MinimalAction.cpp index 019e652dde..7f1f239d16 100644 --- a/Parse/MinimalAction.cpp +++ b/Parse/MinimalAction.cpp @@ -80,6 +80,18 @@ MinimalAction::ObjcStartClassInterface(SourceLocation AtInterafceLoc, return 0; } +Action::DeclTy * +MinimalAction::ObjcStartProtoInterface(SourceLocation AtProtoInterfaceLoc, + IdentifierInfo *ProtocolName, SourceLocation ProtocolLoc, + IdentifierInfo **ProtoRefNames, unsigned NumProtoRefs) { + + TypeNameInfo *TI = + new TypeNameInfo(1, ProtocolName->getFETokenInfo()); + + ProtocolName->setFETokenInfo(TI); + return 0; +} + /// ObjcClassDeclaration - /// Scope will always be top level file scope. Action::DeclTy * diff --git a/Parse/ParseObjc.cpp b/Parse/ParseObjc.cpp index 87cc277add..c2cf61d367 100644 --- a/Parse/ParseObjc.cpp +++ b/Parse/ParseObjc.cpp @@ -154,7 +154,7 @@ Parser::DeclTy *Parser::ParseObjCAtInterfaceDeclaration( if (attrList) // categories don't support attributes. Diag(Tok, diag::err_objc_no_attributes_on_category); - ParseObjCInterfaceDeclList(0/*FIXME*/); + ParseObjCInterfaceDeclList(0, tok::objc_not_keyword/*FIXME*/); // The @ sign was already consumed by ParseObjCInterfaceDeclList(). if (Tok.isObjCAtKeyword(tok::objc_end)) { @@ -190,7 +190,7 @@ Parser::DeclTy *Parser::ParseObjCAtInterfaceDeclaration( if (Tok.getKind() == tok::l_brace) ParseObjCClassInstanceVariables(ClsType); - ParseObjCInterfaceDeclList(ClsType); + ParseObjCInterfaceDeclList(ClsType, tok::objc_interface); // The @ sign was already consumed by ParseObjCInterfaceDeclList(). if (Tok.isObjCAtKeyword(tok::objc_end)) { @@ -213,8 +213,10 @@ Parser::DeclTy *Parser::ParseObjCAtInterfaceDeclaration( /// @required /// @optional /// -void Parser::ParseObjCInterfaceDeclList(DeclTy *interfaceDecl) { +void Parser::ParseObjCInterfaceDeclList(DeclTy *interfaceDecl, + tok::ObjCKeywordKind contextKey) { llvm::SmallVector allMethods; + tok::ObjCKeywordKind pi = tok::objc_not_keyword; while (1) { if (Tok.getKind() == tok::at) { SourceLocation AtLoc = ConsumeToken(); // the "@" @@ -224,10 +226,14 @@ void Parser::ParseObjCInterfaceDeclList(DeclTy *interfaceDecl) { break; } else if (ocKind == tok::objc_required) { // protocols only ConsumeToken(); - continue; + pi = ocKind; + if (contextKey != tok::objc_protocol) + Diag(AtLoc, diag::err_objc_protocol_required); } else if (ocKind == tok::objc_optional) { // protocols only ConsumeToken(); - continue; + pi = ocKind; + if (contextKey != tok::objc_protocol) + Diag(AtLoc, diag::err_objc_protocol_optional); } else if (ocKind == tok::objc_property) { ParseObjCPropertyDecl(interfaceDecl); continue; @@ -237,7 +243,8 @@ void Parser::ParseObjCInterfaceDeclList(DeclTy *interfaceDecl) { } } if (Tok.getKind() == tok::minus || Tok.getKind() == tok::plus) { - allMethods.push_back(ParseObjCMethodPrototype(interfaceDecl)); + DeclTy *methodPrototype = ParseObjCMethodPrototype(interfaceDecl, pi); + allMethods.push_back(methodPrototype); // Consume the ';' here, since ParseObjCMethodPrototype() is re-used for // method definitions. ExpectAndConsume(tok::semi, diag::err_expected_semi_after,"method proto"); @@ -360,14 +367,15 @@ void Parser::ParseObjCPropertyDecl(DeclTy *interfaceDecl) { /// objc-method-attributes: [OBJC2] /// __attribute__((deprecated)) /// -Parser::DeclTy *Parser::ParseObjCMethodPrototype(DeclTy *CDecl) { +Parser::DeclTy *Parser::ParseObjCMethodPrototype(DeclTy *IDecl, + tok::ObjCKeywordKind& pi) { assert((Tok.getKind() == tok::minus || Tok.getKind() == tok::plus) && "expected +/-"); tok::TokenKind methodType = Tok.getKind(); SourceLocation methodLoc = ConsumeToken(); - DeclTy *MDecl = ParseObjCMethodDecl(methodType, methodLoc); + DeclTy *MDecl = ParseObjCMethodDecl(IDecl, pi, methodType, methodLoc); // Since this rule is used for both method declarations and definitions, // the caller is (optionally) responsible for consuming the ';'. return MDecl; @@ -476,8 +484,10 @@ Parser::TypeTy *Parser::ParseObjCTypeName() { /// objc-keyword-attributes: [OBJC2] /// __attribute__((unused)) /// -Parser::DeclTy *Parser::ParseObjCMethodDecl(tok::TokenKind mType, - SourceLocation mLoc) { +Parser::DeclTy *Parser::ParseObjCMethodDecl(DeclTy *IDecl, + tok::ObjCKeywordKind& pi, + tok::TokenKind mType, SourceLocation mLoc) { + TypeTy *ReturnType = 0; AttributeList *methodAttrs = 0; @@ -542,7 +552,8 @@ Parser::DeclTy *Parser::ParseObjCMethodDecl(tok::TokenKind mType, // If attributes exist after the method, parse them. if (getLang().ObjC2 && Tok.getKind() == tok::kw___attribute) methodAttrs = ParseAttributes(); - return Actions.ObjcBuildMethodDeclaration(mLoc, mType, ReturnType, + return Actions.ObjcBuildMethodDeclaration(IDecl, pi, mLoc, mType, + ReturnType, &KeyInfo[0], KeyInfo.size(), methodAttrs); } else if (!selIdent) { @@ -552,8 +563,9 @@ Parser::DeclTy *Parser::ParseObjCMethodDecl(tok::TokenKind mType, if (getLang().ObjC2 && Tok.getKind() == tok::kw___attribute) methodAttrs = ParseAttributes(); - return Actions.ObjcBuildMethodDeclaration(mLoc, mType, ReturnType, selIdent, - methodAttrs); + return Actions.ObjcBuildMethodDeclaration(IDecl, pi, + mLoc, mType, ReturnType, + selIdent, methodAttrs); } /// objc-protocol-refs: @@ -724,12 +736,17 @@ Parser::DeclTy *Parser::ParseObjCAtProtocolDeclaration(SourceLocation AtLoc) { return 0; // FIXME } // Last, and definitely not least, parse a protocol declaration. + llvm::SmallVector ProtocolRefs; if (Tok.getKind() == tok::less) { - llvm::SmallVector ProtocolRefs; if (ParseObjCProtocolReferences(ProtocolRefs)) return 0; } - ParseObjCInterfaceDeclList(0/*FIXME*/); + + DeclTy *ProtoType = Actions.ObjcStartProtoInterface(AtLoc, + protocolName, nameLoc, + &ProtocolRefs[0], + ProtocolRefs.size()); + ParseObjCInterfaceDeclList(ProtoType, tok::objc_protocol); // The @ sign was already consumed by ParseObjCInterfaceDeclList(). if (Tok.isObjCAtKeyword(tok::objc_end)) { @@ -900,7 +917,9 @@ Parser::DeclTy *Parser::ParseObjCPropertyDynamic(SourceLocation atLoc) { void Parser::ParseObjCInstanceMethodDefinition() { assert(Tok.getKind() == tok::minus && "ParseObjCInstanceMethodDefinition(): Expected '-'"); - ParseObjCMethodPrototype(ObjcImpDecl); + // FIXME: @optional/@protocol?? + tok::ObjCKeywordKind pi = tok::objc_not_keyword; + ParseObjCMethodPrototype(ObjcImpDecl, pi); // parse optional ';' if (Tok.getKind() == tok::semi) ConsumeToken(); @@ -918,7 +937,9 @@ void Parser::ParseObjCInstanceMethodDefinition() { void Parser::ParseObjCClassMethodDefinition() { assert(Tok.getKind() == tok::plus && "ParseObjCClassMethodDefinition(): Expected '+'"); - ParseObjCMethodPrototype(ObjcImpDecl); + // FIXME: @optional/@protocol?? + tok::ObjCKeywordKind pi = tok::objc_not_keyword; + ParseObjCMethodPrototype(ObjcImpDecl, pi); // parse optional ';' if (Tok.getKind() == tok::semi) ConsumeToken(); diff --git a/Sema/Sema.h b/Sema/Sema.h index 5272444086..b50993e7e2 100644 --- a/Sema/Sema.h +++ b/Sema/Sema.h @@ -358,17 +358,25 @@ public: IdentifierInfo **ProtocolNames, unsigned NumProtocols, AttributeList *AttrList); + virtual DeclTy *ObjcStartProtoInterface(SourceLocation AtProtoInterfaceLoc, + IdentifierInfo *ProtocolName, SourceLocation ProtocolLoc, + IdentifierInfo **ProtoRefNames, unsigned NumProtoRefs); + virtual DeclTy *ObjcClassDeclaration(Scope *S, SourceLocation AtClassLoc, IdentifierInfo **IdentList, unsigned NumElts); virtual void ObjcAddMethodsToClass(DeclTy *ClassDecl, DeclTy **allMethods, unsigned allNum); - virtual DeclTy *ObjcBuildMethodDeclaration(SourceLocation MethodLoc, + virtual DeclTy *ObjcBuildMethodDeclaration(DeclTy *InterfaceDecl, + tok::ObjCKeywordKind& pi, + SourceLocation MethodLoc, tok::TokenKind MethodType, TypeTy *ReturnType, ObjcKeywordDecl *Keywords, unsigned NumKeywords, AttributeList *AttrList); - virtual DeclTy *ObjcBuildMethodDeclaration(SourceLocation MethodLoc, + virtual DeclTy *ObjcBuildMethodDeclaration(DeclTy *InterfaceDecl, + tok::ObjCKeywordKind& pi, + SourceLocation MethodLoc, tok::TokenKind MethodType, TypeTy *ReturnType, IdentifierInfo *SelectorName, AttributeList *AttrList); diff --git a/Sema/SemaDecl.cpp b/Sema/SemaDecl.cpp index 051ba7665b..24b6309b1a 100644 --- a/Sema/SemaDecl.cpp +++ b/Sema/SemaDecl.cpp @@ -28,7 +28,8 @@ using namespace clang; Sema::DeclTy *Sema::isTypeName(const IdentifierInfo &II, Scope *S) const { Decl *IIDecl = II.getFETokenInfo(); if (dyn_cast_or_null(IIDecl) || - dyn_cast_or_null(IIDecl)) + dyn_cast_or_null(IIDecl) || + dyn_cast_or_null(IIDecl)) return IIDecl; return 0; } @@ -877,6 +878,20 @@ Sema::DeclTy *Sema::ObjcStartClassInterface(SourceLocation AtInterfaceLoc, return IDecl; } +Sema::DeclTy *Sema::ObjcStartProtoInterface(SourceLocation AtProtoInterfaceLoc, + IdentifierInfo *ProtocolName, SourceLocation ProtocolLoc, + IdentifierInfo **ProtoRefNames, unsigned NumProtoRefs) { + assert(ProtocolName && "Missing protocol identifier"); + ObjcProtocolDecl *PDecl; + + PDecl = new ObjcProtocolDecl(AtProtoInterfaceLoc, ProtocolName); + + // Chain & install the protocol decl into the identifier. + PDecl->setNext(ProtocolName->getFETokenInfo()); + ProtocolName->setFETokenInfo(PDecl); + return PDecl; +} + /// ObjcClassDeclaration - /// Scope will always be top level file scope. Action::DeclTy * @@ -1214,19 +1229,17 @@ void Sema::ActOnFields(SourceLocation RecLoc, DeclTy *RecDecl, } } -void Sema::ObjcAddMethodsToClass(DeclTy *ClassDecl, - DeclTy **allMethods, unsigned allNum) { +void Sema::ObjcAddMethodsToClass(DeclTy *ClassDecl, + DeclTy **allMethods, unsigned allNum) { // FIXME: Fix this when we can handle methods declared in protocols. // See Parser::ParseObjCAtProtocolDeclaration if (!ClassDecl) return; - ObjcInterfaceDecl *Interface = cast( - static_cast(ClassDecl)); llvm::SmallVector insMethods; llvm::SmallVector clsMethods; for (unsigned i = 0; i < allNum; i++ ) { - ObjcMethodDecl *Method = + ObjcMethodDecl *Method = cast_or_null(static_cast(allMethods[i])); if (!Method) continue; // Already issued a diagnostic. if (Method->isInstance()) @@ -1234,12 +1247,26 @@ void Sema::ObjcAddMethodsToClass(DeclTy *ClassDecl, else clsMethods.push_back(Method); } - Interface->ObjcAddMethods(&insMethods[0], insMethods.size(), - &clsMethods[0], clsMethods.size()); + if (isa(static_cast(ClassDecl))) { + ObjcInterfaceDecl *Interface = cast( + static_cast(ClassDecl)); + Interface->ObjcAddMethods(&insMethods[0], insMethods.size(), + &clsMethods[0], clsMethods.size()); + } + else if (isa(static_cast(ClassDecl))) { + ObjcProtocolDecl *Protocol = cast( + static_cast(ClassDecl)); + Protocol->ObjcAddProtoMethods(&insMethods[0], insMethods.size(), + &clsMethods[0], clsMethods.size()); + } + else + assert(0 && "Sema::ObjcAddMethodsToClass(): Unknown DeclTy"); return; } -Sema::DeclTy *Sema::ObjcBuildMethodDeclaration(SourceLocation MethodLoc, +Sema::DeclTy *Sema::ObjcBuildMethodDeclaration(DeclTy *IDecl, + tok::ObjCKeywordKind& pi, + SourceLocation MethodLoc, tok::TokenKind MethodType, TypeTy *ReturnType, ObjcKeywordDecl *Keywords, unsigned NumKeywords, AttributeList *AttrList) { @@ -1277,21 +1304,57 @@ Sema::DeclTy *Sema::ObjcBuildMethodDeclaration(SourceLocation MethodLoc, } QualType resultDeclType = QualType::getFromOpaquePtr(ReturnType); ObjcMethodDecl* ObjcMethod; - ObjcMethod = new ObjcMethodDecl(MethodLoc, SelName, resultDeclType, - 0, -1, AttrList, MethodType == tok::minus); - ObjcMethod->setMethodParams(&Params[0], NumKeywords); +// FIXME: Added !IDecl for now to handle @implementation + if (!IDecl || isa(static_cast(IDecl))) { + ObjcMethod = new ObjcMethodDecl(MethodLoc, SelName, resultDeclType, + 0, -1, AttrList, MethodType == tok::minus); + ObjcMethod->setMethodParams(&Params[0], NumKeywords); + } + else if (isa(static_cast(IDecl))) { + ObjcMethod = new ObjcProtoMethodDecl(MethodLoc, SelName, resultDeclType, + 0, -1, AttrList, MethodType == tok::minus); + ObjcMethod->setMethodParams(&Params[0], NumKeywords); + if (pi == tok::objc_optional) + dyn_cast(ObjcMethod)-> + setDeclImplementation(ObjcProtoMethodDecl::Optional); + else + dyn_cast(ObjcMethod)-> + setDeclImplementation(ObjcProtoMethodDecl::Required); + } + else + assert(0 && "Sema::ObjcBuildMethodDeclaration(): Unknown DeclTy"); return ObjcMethod; } -Sema::DeclTy *Sema::ObjcBuildMethodDeclaration(SourceLocation MethodLoc, +Sema::DeclTy *Sema::ObjcBuildMethodDeclaration(DeclTy *IDecl, + tok::ObjCKeywordKind& pi, + SourceLocation MethodLoc, tok::TokenKind MethodType, TypeTy *ReturnType, IdentifierInfo *SelectorName, AttributeList *AttrList) { const char *methodName = SelectorName->getName(); SelectorInfo &SelName = Context.getSelectorInfo(methodName, methodName+strlen(methodName)); QualType resultDeclType = QualType::getFromOpaquePtr(ReturnType); - return new ObjcMethodDecl(MethodLoc, SelName, resultDeclType, 0, -1, - AttrList, MethodType == tok::minus); + ObjcMethodDecl* ObjcMethod; +// FIXME: Remove after IDecl is always non-null + if (!IDecl || isa(static_cast(IDecl))) { + ObjcMethod = new ObjcMethodDecl(MethodLoc, SelName, resultDeclType, 0, -1, + AttrList, MethodType == tok::minus); + } + else if (isa(static_cast(IDecl))) { + ObjcMethod = new ObjcProtoMethodDecl(MethodLoc, SelName, resultDeclType, + 0, -1, + AttrList, MethodType == tok::minus); + if (pi == tok::objc_optional) + dyn_cast(ObjcMethod)-> + setDeclImplementation(ObjcProtoMethodDecl::Optional); + else + dyn_cast(ObjcMethod)-> + setDeclImplementation(ObjcProtoMethodDecl::Required); + } + else + assert(0 && "Sema::ObjcBuildMethodDeclaration(): Unknown DeclTy"); + return ObjcMethod; } Sema::DeclTy *Sema::ActOnEnumConstant(Scope *S, DeclTy *theEnumDecl, diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index 96c6657a75..683e98489f 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -670,7 +670,7 @@ public: /// ObjcProtoMethodDecl - Each instance represents a method declared /// in a protocol. /// -class ObjcProtoMethodDecl : ObjcMethodDecl { +class ObjcProtoMethodDecl : public ObjcMethodDecl { public: ObjcProtoMethodDecl(SourceLocation L, SelectorInfo &Id, QualType T, ParmVarDecl **paramInfo = 0, int numParams=-1, @@ -710,8 +710,8 @@ public: ProtoClsMethods(0), NumProtoClsMethods(-1), isForwardProtoDecl(FD) { } - void ObjcAddProtoMethods(ObjcProtoMethodDecl **insMethods, unsigned numInsMembers, - ObjcProtoMethodDecl **clsMethods, unsigned numClsMembers); + void ObjcAddProtoMethods(ObjcMethodDecl **insMethods, unsigned numInsMembers, + ObjcMethodDecl **clsMethods, unsigned numClsMembers); static bool classof(const Decl *D) { return D->getKind() == ObjcProtocol; diff --git a/include/clang/Basic/DiagnosticKinds.def b/include/clang/Basic/DiagnosticKinds.def index bf2947e8bb..30253f7226 100644 --- a/include/clang/Basic/DiagnosticKinds.def +++ b/include/clang/Basic/DiagnosticKinds.def @@ -402,6 +402,10 @@ DIAG(err_objc_expected_equal, ERROR, "setter/getter expects '=' followed by name") DIAG(err_objc_expected_property_attr, ERROR, "unknown property attribute detected") +DIAG(err_objc_protocol_required, ERROR, + "@required may be specified in protocols only") +DIAG(err_objc_protocol_optional, ERROR, + "@optional may be specified in protocols only") //===----------------------------------------------------------------------===// // Semantic Analysis diff --git a/include/clang/Parse/Action.h b/include/clang/Parse/Action.h index 548ff1a7d7..960e4154fe 100644 --- a/include/clang/Parse/Action.h +++ b/include/clang/Parse/Action.h @@ -448,13 +448,20 @@ public: DeclTy **allMethods, unsigned allNum) { return; } - virtual DeclTy *ObjcBuildMethodDeclaration( + virtual DeclTy *ObjcStartProtoInterface(SourceLocation AtProtoInterfaceLoc, + IdentifierInfo *ProtocolName, SourceLocation ProtocolLoc, + IdentifierInfo **ProtoRefNames, unsigned NumProtoRefs) { + return 0; + } + virtual DeclTy *ObjcBuildMethodDeclaration(DeclTy *IDecl, + tok::ObjCKeywordKind& pi, SourceLocation MethodLoc, tok::TokenKind MethodType, TypeTy *ReturnType, ObjcKeywordDecl *Keywords, unsigned NumKeywords, AttributeList *AttrList) { return 0; } - virtual DeclTy *ObjcBuildMethodDeclaration( + virtual DeclTy *ObjcBuildMethodDeclaration(DeclTy *IDecl, + tok::ObjCKeywordKind& pi, SourceLocation MethodLoc, tok::TokenKind MethodType, TypeTy *ReturnType, IdentifierInfo *SelectorName, AttributeList *AttrList) { return 0; @@ -534,6 +541,10 @@ public: IdentifierInfo *SuperName, SourceLocation SuperLoc, IdentifierInfo **ProtocolNames, unsigned NumProtocols, AttributeList *AttrList); + virtual DeclTy *ObjcStartProtoInterface(SourceLocation AtProtoInterfaceLoc, + IdentifierInfo *ProtocolName, SourceLocation ProtocolLoc, + IdentifierInfo **ProtoRefNames, unsigned NumProtoRefs); + }; } // end namespace clang diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index 7d5cd1a637..89fd68eebd 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -260,7 +260,8 @@ private: AttributeList *prefixAttrs = 0); void ParseObjCClassInstanceVariables(DeclTy *interfaceDecl); bool ParseObjCProtocolReferences(llvm::SmallVectorImpl &); - void ParseObjCInterfaceDeclList(DeclTy *interfaceDecl); + void ParseObjCInterfaceDeclList(DeclTy *interfaceDecl, + tok::ObjCKeywordKind contextKey); DeclTy *ParseObjCAtProtocolDeclaration(SourceLocation atLoc); DeclTy *ObjcImpDecl; @@ -288,8 +289,11 @@ private: TypeTy *ParseObjCTypeName(); void ParseObjCMethodRequirement(); - DeclTy *ParseObjCMethodPrototype(DeclTy *classOrCat); - DeclTy *ParseObjCMethodDecl(tok::TokenKind mType, SourceLocation mLoc); + DeclTy *ParseObjCMethodPrototype(DeclTy *classOrCat, + tok::ObjCKeywordKind& pi); + DeclTy *ParseObjCMethodDecl(DeclTy *CDecl, tok::ObjCKeywordKind& pi, + tok::TokenKind mType, + SourceLocation mLoc); void ParseObjCPropertyAttribute(DeclTy *interfaceDecl); void ParseObjCPropertyDecl(DeclTy *interfaceDecl); diff --git a/test/Sema/protocol-test-1.m b/test/Sema/protocol-test-1.m new file mode 100644 index 0000000000..37070d9cd0 --- /dev/null +++ b/test/Sema/protocol-test-1.m @@ -0,0 +1,18 @@ +@protocol PROTO1 +@required +- (int) FooBar; +@optional +- (void) MyMethod1; ++ (int) S; +@end + +@interface INTF1 +@required // expected-error {{@required may be specified in protocols only}} +- (int) FooBar; +- (int) FooBar1; +- (int) FooBar2; +@optional // expected-error {{@optional may be specified in protocols only}} ++ (int) C; + +- (int)I; +@end