The goal of this commit is to get just enough Sema support to recognize Objective-C classes
as types. That said, the AST nodes ObjcInterfaceDecl, ObjcInterfaceType, and ObjcClassDecl are *very*
preliminary.
The good news is we no longer need -parse-noop (aka MinimalActions) to parse cocoa.m.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@41752 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/Parse/ParseObjc.cpp b/Parse/ParseObjc.cpp
index 39772a3..6557c41 100644
--- a/Parse/ParseObjc.cpp
+++ b/Parse/ParseObjc.cpp
@@ -37,7 +37,7 @@
case tok::objc_protocol:
return ParseObjCAtProtocolDeclaration(AtLoc);
case tok::objc_implementation:
- return ParseObjCAtImplementationDeclaration(AtLoc);
+ return ObjcImpDecl = ParseObjCAtImplementationDeclaration(AtLoc);
case tok::objc_end:
return ParseObjCAtEndDeclaration(AtLoc);
case tok::objc_compatibility_alias:
@@ -80,8 +80,8 @@
if (ExpectAndConsume(tok::semi, diag::err_expected_semi_after, "@class"))
return 0;
- return Actions.ParsedObjcClassDeclaration(CurScope,
- &ClassNames[0], ClassNames.size());
+ return Actions.ObjcClassDeclaration(CurScope, atLoc,
+ &ClassNames[0], ClassNames.size());
}
///
@@ -154,8 +154,7 @@
if (attrList) // categories don't support attributes.
Diag(Tok, diag::err_objc_no_attributes_on_category);
- llvm::SmallVector<DeclTy*, 64> MethodDecls;
- ParseObjCInterfaceDeclList(0/*FIXME*/, MethodDecls);
+ ParseObjCInterfaceDeclList(0/*FIXME*/);
// The @ sign was already consumed by ParseObjCInterfaceDeclList().
if (Tok.isObjCAtKeyword(tok::objc_end)) {
@@ -169,11 +168,6 @@
IdentifierInfo *superClassId = 0;
SourceLocation superClassLoc;
- // FIXME: temporary hack to grok class names (until we have sema support).
- llvm::SmallVector<IdentifierInfo *, 1> ClassName;
- ClassName.push_back(nameId);
- Actions.ParsedObjcClassDeclaration(CurScope, &ClassName[0], 1);
-
if (Tok.getKind() == tok::colon) { // a super class is specified.
ConsumeToken();
if (Tok.getKind() != tok::identifier) {
@@ -193,12 +187,10 @@
superClassId, superClassLoc, &ProtocolRefs[0],
ProtocolRefs.size(), attrList);
- llvm::SmallVector<DeclTy*, 32> IvarDecls;
if (Tok.getKind() == tok::l_brace)
- ParseObjCClassInstanceVariables(ClsType, IvarDecls);
+ ParseObjCClassInstanceVariables(ClsType);
- llvm::SmallVector<DeclTy*, 64> MethodDecls;
- ParseObjCInterfaceDeclList(ClsType, MethodDecls);
+ ParseObjCInterfaceDeclList(ClsType);
// The @ sign was already consumed by ParseObjCInterfaceDeclList().
if (Tok.isObjCAtKeyword(tok::objc_end)) {
@@ -213,7 +205,7 @@
/// empty
/// objc-interface-decl-list objc-property-decl [OBJC2]
/// objc-interface-decl-list objc-method-requirement [OBJC2]
-/// objc-interface-decl-list objc-method-proto
+/// objc-interface-decl-list objc-method-proto ';'
/// objc-interface-decl-list declaration
/// objc-interface-decl-list ';'
///
@@ -221,9 +213,7 @@
/// @required
/// @optional
///
-void Parser::ParseObjCInterfaceDeclList(
- DeclTy *interfaceDecl, llvm::SmallVectorImpl<DeclTy*> &MethodDecls) {
- DeclTy *IDecl = 0;
+void Parser::ParseObjCInterfaceDeclList(DeclTy *interfaceDecl) {
while (1) {
if (Tok.getKind() == tok::at) {
SourceLocation AtLoc = ConsumeToken(); // the "@"
@@ -246,8 +236,10 @@
}
}
if (Tok.getKind() == tok::minus || Tok.getKind() == tok::plus) {
- IDecl = ParseObjCMethodPrototype(true);
- MethodDecls.push_back(IDecl);
+ ParseObjCMethodPrototype(interfaceDecl);
+ // Consume the ';' here, since ParseObjCMethodPrototype() is re-used for
+ // method definitions.
+ ExpectAndConsume(tok::semi, diag::err_expected_semi_after, "method proto");
continue;
}
if (Tok.getKind() == tok::semi)
@@ -257,8 +249,7 @@
else {
// FIXME: as the name implies, this rule allows function definitions.
// We could pass a flag or check for functions during semantic analysis.
- IDecl = ParseDeclarationOrFunctionDefinition();
- MethodDecls.push_back(IDecl);
+ ParseDeclarationOrFunctionDefinition();
}
}
}
@@ -355,10 +346,9 @@
}
}
-/// objc-methodproto:
+/// objc-method-proto:
/// objc-instance-method objc-method-decl objc-method-attributes[opt]
-/// ';'[opt]
-/// objc-class-method objc-method-decl objc-method-attributes[opt] ';'[opt]
+/// objc-class-method objc-method-decl objc-method-attributes[opt]
///
/// objc-instance-method: '-'
/// objc-class-method: '+'
@@ -366,19 +356,25 @@
/// objc-method-attributes: [OBJC2]
/// __attribute__((deprecated))
///
-Parser::DeclTy *Parser::ParseObjCMethodPrototype(bool decl) {
+Parser::DeclTy *Parser::ParseObjCMethodPrototype(DeclTy *CDecl) {
assert((Tok.getKind() == tok::minus || Tok.getKind() == tok::plus) &&
"expected +/-");
tok::TokenKind methodType = Tok.getKind();
SourceLocation methodLoc = ConsumeToken();
- // FIXME: deal with "context sensitive" protocol qualifiers in prototypes
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);
- if (decl)
- // Consume the ';'.
- ExpectAndConsume(tok::semi, diag::err_expected_semi_after, "method proto");
+ // Since this rule is used for both method declarations and definitions,
+ // the caller is responsible for consuming the ';'.
return MDecl;
}
@@ -546,24 +542,13 @@
Declarator ParmDecl(DS, Declarator::PrototypeContext);
ParseDeclarator(ParmDecl);
}
- AttributeList *methodAttrs = 0;
- // If attributes exist after the method, parse them.
- if (getLang().ObjC2 && Tok.getKind() == tok::kw___attribute)
- methodAttrs = ParseAttributes();
-
// FIXME: Add support for optional parmameter list...
return Actions.ObjcBuildMethodDeclaration(mLoc, mType, ReturnType,
- &KeyInfo[0], KeyInfo.size(),
- methodAttrs);
+ &KeyInfo[0], KeyInfo.size());
} else if (!selIdent) {
Diag(Tok, diag::err_expected_ident); // missing selector name.
}
- AttributeList *methodAttrs = 0;
- // 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);
+ return Actions.ObjcBuildMethodDeclaration(mLoc, mType, ReturnType, selIdent);
}
/// objc-protocol-refs:
@@ -612,9 +597,9 @@
/// objc-instance-variable-decl:
/// struct-declaration
///
-void Parser::ParseObjCClassInstanceVariables(DeclTy *interfaceDecl,
- llvm::SmallVectorImpl<DeclTy*> &IvarDecls) {
+void Parser::ParseObjCClassInstanceVariables(DeclTy *interfaceDecl) {
assert(Tok.getKind() == tok::l_brace && "expected {");
+ llvm::SmallVector<DeclTy*, 16> IvarDecls;
SourceLocation LBraceLoc = ConsumeBrace(); // the "{"
@@ -648,7 +633,10 @@
}
}
ParseStructDeclaration(interfaceDecl, IvarDecls);
-
+ for (unsigned i = 0; i < IvarDecls.size(); i++)
+ Actions.ObjcAddInstanceVariable(interfaceDecl, IvarDecls[i], visibility);
+ IvarDecls.clear();
+
if (Tok.getKind() == tok::semi) {
ConsumeToken();
} else if (Tok.getKind() == tok::r_brace) {
@@ -671,14 +659,14 @@
/// objc-protocol-definition:
/// @protocol identifier
/// objc-protocol-refs[opt]
-/// objc-methodprotolist
+/// objc-interface-decl-list
/// @end
///
/// objc-protocol-forward-reference:
/// @protocol identifier-list ';'
///
/// "@protocol identifier ;" should be resolved as "@protocol
-/// identifier-list ;": objc-methodprotolist may not start with a
+/// identifier-list ;": objc-interface-decl-list may not start with a
/// semicolon in the first alternative if objc-protocol-refs are omitted.
Parser::DeclTy *Parser::ParseObjCAtProtocolDeclaration(SourceLocation AtLoc) {
@@ -727,8 +715,7 @@
if (ParseObjCProtocolReferences(ProtocolRefs))
return 0;
}
- llvm::SmallVector<DeclTy*, 64> MethodDecls;
- ParseObjCInterfaceDeclList(0/*FIXME*/, MethodDecls);
+ ParseObjCInterfaceDeclList(0/*FIXME*/);
// The @ sign was already consumed by ParseObjCInterfaceDeclList().
if (Tok.isObjCAtKeyword(tok::objc_end)) {
@@ -794,9 +781,8 @@
}
ConsumeToken(); // Consume super class name
}
- llvm::SmallVector<DeclTy*, 32> IvarDecls;
if (Tok.getKind() == tok::l_brace)
- ParseObjCClassInstanceVariables(0/*FIXME*/, IvarDecls); // we have ivars
+ ParseObjCClassInstanceVariables(0/*FIXME*/); // we have ivars
return 0;
}
@@ -895,12 +881,12 @@
return 0;
}
-/// objc-method-def: objc-methodproto ';'[opt] '{' body '}'
+/// objc-method-def: objc-method-proto ';'[opt] '{' body '}'
///
void Parser::ParseObjCInstanceMethodDefinition() {
assert(Tok.getKind() == tok::minus &&
"ParseObjCInstanceMethodDefinition(): Expected '-'");
- ParseObjCMethodPrototype(false);
+ ParseObjCMethodPrototype(ObjcImpDecl);
// parse optional ';'
if (Tok.getKind() == tok::semi)
ConsumeToken();
@@ -913,12 +899,12 @@
StmtResult FnBody = ParseCompoundStatementBody();
}
-/// objc-method-def: objc-methodproto ';'[opt] '{' body '}'
+/// objc-method-def: objc-method-proto ';'[opt] '{' body '}'
///
void Parser::ParseObjCClassMethodDefinition() {
assert(Tok.getKind() == tok::plus &&
"ParseObjCClassMethodDefinition(): Expected '+'");
- ParseObjCMethodPrototype(false);
+ ParseObjCMethodPrototype(ObjcImpDecl);
// parse optional ';'
if (Tok.getKind() == tok::semi)
ConsumeToken();