[cfe-commits] r41275 - in /cfe/trunk: Parse/ParseObjc.cpp include/clang/Basic/DiagnosticKinds.def include/clang/Basic/TokenKinds.def include/clang/Parse/Parser.h
Steve Naroff
snaroff at apple.com
Wed Aug 22 09:35:03 PDT 2007
Author: snaroff
Date: Wed Aug 22 11:35:03 2007
New Revision: 41275
URL: http://llvm.org/viewvc/llvm-project?rev=41275&view=rev
Log:
Add support for parsing method prototypes (and other stuff required by @interface).
Still need to finish Parser::ParseObjCMethodDecl(). Before I do, I need to do a minor
refactoring of ParseDeclarationOrFunctionDefinition(), to disallow function definitions.
At the moment, @inteface allows function defs (which is incorrect).
Modified:
cfe/trunk/Parse/ParseObjc.cpp
cfe/trunk/include/clang/Basic/DiagnosticKinds.def
cfe/trunk/include/clang/Basic/TokenKinds.def
cfe/trunk/include/clang/Parse/Parser.h
Modified: cfe/trunk/Parse/ParseObjc.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Parse/ParseObjc.cpp?rev=41275&r1=41274&r2=41275&view=diff
==============================================================================
--- cfe/trunk/Parse/ParseObjc.cpp (original)
+++ cfe/trunk/Parse/ParseObjc.cpp Wed Aug 22 11:35:03 2007
@@ -120,7 +120,7 @@
return 0;
}
// We have a class or category name - consume it.
- IdentifierInfo *nameId = Tok.getIdentifierInfo();
+ // IdentifierInfo *nameId = Tok.getIdentifierInfo();
SourceLocation nameLoc = ConsumeToken();
if (Tok.getKind() == tok::l_paren) { // we have a category
@@ -147,18 +147,15 @@
if (attrList) // categories don't support attributes.
Diag(Tok, diag::err_objc_no_attributes_on_category);
- //ParseObjCInterfaceDeclList();
+ ParseObjCInterfaceDeclList(0/*FIXME*/);
- if (Tok.getKind() != tok::at) { // check for @end
- Diag(Tok, diag::err_objc_missing_end);
+ // The @ sign was already consumed by ParseObjCInterfaceDeclList().
+ if (Tok.getKind() == tok::identifier &&
+ Tok.getIdentifierInfo()->getObjCKeywordID() == tok::objc_end) {
+ ConsumeToken(); // the "end" identifier
return 0;
}
- SourceLocation atEndLoc = ConsumeToken(); // eat the @ sign
- if (Tok.getIdentifierInfo()->getObjCKeywordID() != tok::objc_end) {
- Diag(Tok, diag::err_objc_missing_end);
- return 0;
- }
- ConsumeToken(); // the "end" identifier
+ Diag(Tok, diag::err_objc_missing_end);
return 0;
}
// Parse a class interface.
@@ -183,32 +180,173 @@
if (Tok.getKind() == tok::l_brace)
ParseObjCClassInstanceVariables(0/*FIXME*/);
- //ParseObjCInterfaceDeclList();
-
- if (Tok.getKind() != tok::at) { // check for @end
- Diag(Tok, diag::err_objc_missing_end);
- return 0;
- }
- SourceLocation atEndLoc = ConsumeToken(); // eat the @ sign
- if (Tok.getIdentifierInfo()->getObjCKeywordID() != tok::objc_end) {
- Diag(Tok, diag::err_objc_missing_end);
+ ParseObjCInterfaceDeclList(0/*FIXME*/);
+
+ // The @ sign was already consumed by ParseObjCInterfaceDeclList().
+ if (Tok.getKind() == tok::identifier &&
+ Tok.getIdentifierInfo()->getObjCKeywordID() == tok::objc_end) {
+ ConsumeToken(); // the "end" identifier
return 0;
}
- ConsumeToken(); // the "end" identifier
+ Diag(Tok, diag::err_objc_missing_end);
return 0;
}
/// objc-interface-decl-list:
/// empty
-/// objc-interface-decl-list objc-method-proto
/// 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 declaration
/// objc-interface-decl-list ';'
///
-void Parser::ParseObjCInterfaceDeclList() {
+/// objc-method-requirement: [OBJC2]
+/// @required
+/// @optional
+///
+void Parser::ParseObjCInterfaceDeclList(DeclTy *interfaceDecl) {
+ while (1) {
+ if (Tok.getKind() == tok::at) {
+ SourceLocation AtLoc = ConsumeToken(); // the "@"
+ tok::ObjCKeywordKind ocKind = Tok.getIdentifierInfo()->getObjCKeywordID();
+
+ if (ocKind == tok::objc_end) { // terminate list
+ return;
+ } else if (ocKind == tok::objc_required) { // protocols only
+ ConsumeToken();
+ continue;
+ } else if (ocKind == tok::objc_optional) { // protocols only
+ ConsumeToken();
+ continue;
+ } else if (ocKind == tok::objc_property) {
+ ParseObjCPropertyDecl(AtLoc);
+ continue;
+ } else {
+ Diag(Tok, diag::err_objc_illegal_interface_qual);
+ ConsumeToken();
+ }
+ }
+ if (Tok.getKind() == tok::minus || Tok.getKind() == tok::plus) {
+ ParseObjCMethodPrototype();
+ continue;
+ }
+ if (Tok.getKind() == tok::semi)
+ ConsumeToken();
+ else if (Tok.getKind() == tok::eof)
+ return;
+ else
+ ParseDeclarationOrFunctionDefinition();
+ }
+}
+
+void Parser::ParseObjCPropertyDecl(SourceLocation atLoc) {
assert(0 && "Unimp");
}
+/// objc-methodproto:
+/// objc-instance-method objc-method-decl ';'
+/// objc-class-method objc-method-decl ';'
+///
+/// objc-instance-method: '-'
+/// objc-class-method: '+'
+///
+void Parser::ParseObjCMethodPrototype() {
+ 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
+ ParseObjCMethodDecl(methodType, methodLoc);
+
+ // Consume the ';'.
+ ExpectAndConsume(tok::semi, diag::err_expected_semi_after, "method proto");
+}
+
+/// objc-selector:
+/// identifier
+/// one of
+/// enum struct union if else while do for switch case default
+/// break continue return goto asm sizeof typeof __alignof
+/// unsigned long const short volatile signed restrict _Complex
+/// in out inout bycopy byref oneway int char float double void _Bool
+///
+IdentifierInfo *Parser::ParseObjCSelector() {
+ tok::TokenKind tKind = Tok.getKind();
+ IdentifierInfo *II = 0;
+
+ if (tKind == tok::identifier ||
+ (tKind >= tok::kw_auto && tKind <= tok::kw__Complex)) {
+ // FIXME: make sure the list of keywords jives with gcc. For example,
+ // the above test does not include in/out/inout/bycopy/byref/oneway.
+ II = Tok.getIdentifierInfo();
+ ConsumeToken();
+ }
+ return II;
+}
+
+/// objc-type-name:
+/// '(' objc-type-qualifiers[opt] type-name ')'
+/// '(' objc-type-qualifiers[opt] ')'
+///
+/// objc-type-qualifiers:
+/// objc-type-qualifier
+/// objc-type-qualifiers objc-type-qualifier
+///
+/// objc-type-qualifier: one of
+/// in out inout bycopy byref oneway
+///
+void Parser::ParseObjCTypeName() {
+ assert(Tok.getKind() == tok::l_paren && "expected (");
+
+ SourceLocation LParenLoc = ConsumeParen(), RParenLoc;
+
+ if (isTypeSpecifierQualifier()) {
+ TypeTy *Ty = ParseTypeName();
+
+ assert(Ty && "Parser::ParseObjCTypeName(): missing type");
+ }
+ if (Tok.getKind() != tok::r_paren) {
+ MatchRHSPunctuation(tok::r_paren, LParenLoc);
+ return;
+ }
+ RParenLoc = ConsumeParen();
+}
+
+/// objc-method-decl:
+/// objc-selector
+/// objc-keyword-selector objc-optparmlist
+/// objc-type-name objc-selector
+/// objc-type-name objc-keyword-selector objc-optparmlist
+///
+/// objc-keyword-selector:
+/// objc-keyword-decl
+/// objc-keyword-selector objc-keyword-decl
+///
+/// objc-keyword-decl:
+/// objc-selector ':' objc-type-name identifier
+/// objc-selector ':' identifier
+/// ':' objc-type-name identifier
+/// ':' identifier
+///
+/// objc-optparmlist:
+/// objc-optparms objc-optellipsis
+///
+/// objc-optparms:
+/// empty
+/// objc-opt-parms , parameter-declaration
+///
+/// objc-optellipsis:
+/// empty
+/// , ...
+///
+void Parser::ParseObjCMethodDecl(tok::TokenKind mType, SourceLocation mLoc) {
+ if (Tok.getKind() == tok::l_paren)
+ ParseObjCTypeName();
+ ParseObjCSelector();
+}
+
/// objc-protocol-refs:
/// '<' identifier-list '>'
///
Modified: cfe/trunk/include/clang/Basic/DiagnosticKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticKinds.def?rev=41275&r1=41274&r2=41275&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticKinds.def (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticKinds.def Wed Aug 22 11:35:03 2007
@@ -384,6 +384,8 @@
"missing @end")
DIAG(err_objc_illegal_visibility_spec, ERROR,
"illegal visibility specification")
+DIAG(err_objc_illegal_interface_qual, ERROR,
+ "illegal interface qualifier")
//===----------------------------------------------------------------------===//
// Semantic Analysis
Modified: cfe/trunk/include/clang/Basic/TokenKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/TokenKinds.def?rev=41275&r1=41274&r2=41275&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/TokenKinds.def (original)
+++ cfe/trunk/include/clang/Basic/TokenKinds.def Wed Aug 22 11:35:03 2007
@@ -350,6 +350,8 @@
// I'm guessing this is an objc2 keyword, what are the others?
OBJC2_AT_KEYWORD(property)
OBJC2_AT_KEYWORD(package)
+OBJC2_AT_KEYWORD(required)
+OBJC2_AT_KEYWORD(optional)
// TODO: What to do about context-sensitive keywords like:
// bycopy/byref/in/inout/oneway/out?
Modified: cfe/trunk/include/clang/Parse/Parser.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=41275&r1=41274&r2=41275&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Parser.h (original)
+++ cfe/trunk/include/clang/Parse/Parser.h Wed Aug 22 11:35:03 2007
@@ -260,12 +260,19 @@
AttributeList *prefixAttrs = 0);
void ParseObjCClassInstanceVariables(DeclTy *interfaceDecl);
bool ParseObjCProtocolReferences();
- void ParseObjCInterfaceDeclList();
+ void ParseObjCInterfaceDeclList(DeclTy *interfaceDecl);
DeclTy *ParseObjCAtProtocolDeclaration();
DeclTy *ParseObjCAtImplementationDeclaration();
DeclTy *ParseObjCAtEndDeclaration();
DeclTy *ParseObjCAtAliasDeclaration();
+ IdentifierInfo *ParseObjCSelector();
+ void ParseObjCTypeName();
+ void ParseObjCMethodRequirement();
+ void ParseObjCMethodPrototype();
+ void ParseObjCMethodDecl(tok::TokenKind mType, SourceLocation mLoc);
+ void ParseObjCPropertyDecl(SourceLocation atLoc);
+
void ParseObjCInstanceMethodDeclaration();
void ParseObjCClassMethodDeclaration();
More information about the cfe-commits
mailing list