Early patch to collect objective-c methods inserts them in
class object.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@41801 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/Parse/ParseObjc.cpp b/Parse/ParseObjc.cpp
index 6557c41..19594d8 100644
--- a/Parse/ParseObjc.cpp
+++ b/Parse/ParseObjc.cpp
@@ -214,13 +214,14 @@
/// @optional
///
void Parser::ParseObjCInterfaceDeclList(DeclTy *interfaceDecl) {
+ llvm::SmallVector<DeclTy*, 32> allMethods;
while (1) {
if (Tok.getKind() == tok::at) {
SourceLocation AtLoc = ConsumeToken(); // the "@"
tok::ObjCKeywordKind ocKind = Tok.getObjCKeywordID();
if (ocKind == tok::objc_end) { // terminate list
- return;
+ break;
} else if (ocKind == tok::objc_required) { // protocols only
ConsumeToken();
continue;
@@ -236,7 +237,7 @@
}
}
if (Tok.getKind() == tok::minus || Tok.getKind() == tok::plus) {
- ParseObjCMethodPrototype(interfaceDecl);
+ allMethods.push_back(ParseObjCMethodPrototype(interfaceDecl));
// Consume the ';' here, since ParseObjCMethodPrototype() is re-used for
// method definitions.
ExpectAndConsume(tok::semi, diag::err_expected_semi_after, "method proto");
@@ -245,13 +246,17 @@
if (Tok.getKind() == tok::semi)
ConsumeToken();
else if (Tok.getKind() == tok::eof)
- return;
+ break;
else {
// FIXME: as the name implies, this rule allows function definitions.
// We could pass a flag or check for functions during semantic analysis.
ParseDeclarationOrFunctionDefinition();
}
}
+
+ /// Insert collected methods declarations into the @interface object.
+ Actions.ObjcAddMethodsToClass(interfaceDecl, &allMethods[0], allMethods.size());
+ return;
}
/// Parse property attribute declarations.
@@ -364,15 +369,6 @@
SourceLocation methodLoc = ConsumeToken();
DeclTy *MDecl = ParseObjCMethodDecl(methodType, methodLoc);
-
- AttributeList *methodAttrs = 0;
- // If attributes exist after the method, parse them.
- if (getLang().ObjC2 && Tok.getKind() == tok::kw___attribute)
- methodAttrs = ParseAttributes();
-
- if (CDecl)
- Actions.ObjcAddMethod(CDecl, MDecl, methodAttrs);
-
// Since this rule is used for both method declarations and definitions,
// the caller is responsible for consuming the ';'.
return MDecl;
@@ -484,6 +480,7 @@
Parser::DeclTy *Parser::ParseObjCMethodDecl(tok::TokenKind mType, SourceLocation mLoc) {
TypeTy *ReturnType = 0;
+ AttributeList *methodAttrs = 0;
// Parse the return type.
if (Tok.getKind() == tok::l_paren)
@@ -491,42 +488,42 @@
IdentifierInfo *selIdent = ParseObjCSelector();
llvm::SmallVector<ObjcKeywordInfo, 12> KeyInfo;
- int KeySlot = 0;
if (Tok.getKind() == tok::colon) {
while (1) {
- KeyInfo[KeySlot].SelectorName = selIdent;
+ ObjcKeywordInfo KeyInfoDecl;
+ KeyInfoDecl.SelectorName = selIdent;
// Each iteration parses a single keyword argument.
if (Tok.getKind() != tok::colon) {
Diag(Tok, diag::err_expected_colon);
break;
}
- KeyInfo[KeySlot].ColonLoc = ConsumeToken(); // Eat the ':'.
+ KeyInfoDecl.ColonLoc = ConsumeToken(); // Eat the ':'.
if (Tok.getKind() == tok::l_paren) // Parse the argument type.
- KeyInfo[KeySlot].TypeInfo = ParseObjCTypeName();
+ KeyInfoDecl.TypeInfo = ParseObjCTypeName();
// If attributes exist before the argument name, parse them.
if (getLang().ObjC2 && Tok.getKind() == tok::kw___attribute)
- KeyInfo[KeySlot].AttrList = ParseAttributes();
+ KeyInfoDecl.AttrList = ParseAttributes();
if (Tok.getKind() != tok::identifier) {
Diag(Tok, diag::err_expected_ident); // missing argument name.
break;
}
- KeyInfo[KeySlot].ArgumentName = Tok.getIdentifierInfo();
+ KeyInfoDecl.ArgumentName = Tok.getIdentifierInfo();
ConsumeToken(); // Eat the identifier.
// Rather than call out to the actions, try packaging up the info
// locally, like we do for Declarator.
// FIXME: add Actions.BuildObjCKeyword()
+ KeyInfo.push_back(KeyInfoDecl);
selIdent = ParseObjCSelector();
if (!selIdent && Tok.getKind() != tok::colon)
break;
// We have a selector or a colon, continue parsing.
- KeySlot++;
}
// Parse the (optional) parameter list.
while (Tok.getKind() == tok::comma) {
@@ -543,12 +540,21 @@
ParseDeclarator(ParmDecl);
}
// FIXME: Add support for optional parmameter list...
+ // If attributes exist after the method, parse them.
+ if (getLang().ObjC2 && Tok.getKind() == tok::kw___attribute)
+ methodAttrs = ParseAttributes();
return Actions.ObjcBuildMethodDeclaration(mLoc, mType, ReturnType,
- &KeyInfo[0], KeyInfo.size());
+ &KeyInfo[0], KeyInfo.size(),
+ methodAttrs);
} else if (!selIdent) {
Diag(Tok, diag::err_expected_ident); // missing selector name.
}
- return Actions.ObjcBuildMethodDeclaration(mLoc, mType, ReturnType, selIdent);
+ // If attributes exist after the method, parse them.
+ if (getLang().ObjC2 && Tok.getKind() == tok::kw___attribute)
+ methodAttrs = ParseAttributes();
+
+ return Actions.ObjcBuildMethodDeclaration(mLoc, mType, ReturnType, selIdent,
+ methodAttrs);
}
/// objc-protocol-refs: