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/Parse/MinimalAction.cpp b/Parse/MinimalAction.cpp
index 019e652..7f1f239 100644
--- a/Parse/MinimalAction.cpp
+++ b/Parse/MinimalAction.cpp
@@ -80,6 +80,18 @@
return 0;
}
+Action::DeclTy *
+MinimalAction::ObjcStartProtoInterface(SourceLocation AtProtoInterfaceLoc,
+ IdentifierInfo *ProtocolName, SourceLocation ProtocolLoc,
+ IdentifierInfo **ProtoRefNames, unsigned NumProtoRefs) {
+
+ TypeNameInfo *TI =
+ new TypeNameInfo(1, ProtocolName->getFETokenInfo<TypeNameInfo>());
+
+ 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 87cc277..c2cf61d 100644
--- a/Parse/ParseObjc.cpp
+++ b/Parse/ParseObjc.cpp
@@ -154,7 +154,7 @@
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 @@
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 @@
/// @required
/// @optional
///
-void Parser::ParseObjCInterfaceDeclList(DeclTy *interfaceDecl) {
+void Parser::ParseObjCInterfaceDeclList(DeclTy *interfaceDecl,
+ tok::ObjCKeywordKind contextKey) {
llvm::SmallVector<DeclTy*, 32> allMethods;
+ tok::ObjCKeywordKind pi = tok::objc_not_keyword;
while (1) {
if (Tok.getKind() == tok::at) {
SourceLocation AtLoc = ConsumeToken(); // the "@"
@@ -224,10 +226,14 @@
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 @@
}
}
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 @@
/// 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 @@
/// 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 @@
// 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 @@
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 @@
return 0; // FIXME
}
// Last, and definitely not least, parse a protocol declaration.
+ llvm::SmallVector<IdentifierInfo *, 8> ProtocolRefs;
if (Tok.getKind() == tok::less) {
- llvm::SmallVector<IdentifierInfo *, 8> 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 @@
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::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();