[cfe-commits] r41200 - in /cfe/trunk: Parse/ParseObjc.cpp Parse/Parser.cpp include/clang/Basic/DiagnosticKinds.def include/clang/Parse/Parser.h
Steve Naroff
snaroff at apple.com
Mon Aug 20 14:31:49 PDT 2007
Author: snaroff
Date: Mon Aug 20 16:31:48 2007
New Revision: 41200
URL: http://llvm.org/viewvc/llvm-project?rev=41200&view=rev
Log:
Start parsing ObjC classes/categories!
Next step, refactor Parser::ParseStructUnionBody() so that struct declarations can
be shared with Objective-C (for declaring instance variables).
Modified:
cfe/trunk/Parse/ParseObjc.cpp
cfe/trunk/Parse/Parser.cpp
cfe/trunk/include/clang/Basic/DiagnosticKinds.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=41200&r1=41199&r2=41200&view=diff
==============================================================================
--- cfe/trunk/Parse/ParseObjc.cpp (original)
+++ cfe/trunk/Parse/ParseObjc.cpp Mon Aug 20 16:31:48 2007
@@ -25,7 +25,7 @@
/// [OBJC] objc-protocol-definition [TODO]
/// [OBJC] objc-method-definition [TODO]
/// [OBJC] '@' 'end' [TODO]
-void Parser::ParseObjCAtDirectives() {
+Parser::DeclTy *Parser::ParseObjCAtDirectives() {
SourceLocation AtLoc = ConsumeToken(); // the "@"
IdentifierInfo *II = Tok.getIdentifierInfo();
@@ -33,7 +33,7 @@
case tok::objc_class:
return ParseObjCAtClassDeclaration(AtLoc);
case tok::objc_interface:
- return ParseObjCAtInterfaceDeclaration();
+ return ParseObjCAtInterfaceDeclaration(AtLoc);
case tok::objc_protocol:
return ParseObjCAtProtocolDeclaration();
case tok::objc_implementation:
@@ -45,6 +45,7 @@
default:
Diag(AtLoc, diag::err_unexpected_at);
SkipUntil(tok::semi);
+ return 0;
}
}
@@ -52,7 +53,7 @@
/// objc-class-declaration:
/// '@' 'class' identifier-list ';'
///
-void Parser::ParseObjCAtClassDeclaration(SourceLocation atLoc) {
+Parser::DeclTy *Parser::ParseObjCAtClassDeclaration(SourceLocation atLoc) {
ConsumeToken(); // the identifier "class"
llvm::SmallVector<IdentifierInfo *, 8> ClassNames;
@@ -60,7 +61,7 @@
if (Tok.getKind() != tok::identifier) {
Diag(Tok, diag::err_expected_ident);
SkipUntil(tok::semi);
- return;
+ return 0;
}
ClassNames.push_back(Tok.getIdentifierInfo());
@@ -74,26 +75,232 @@
// Consume the ';'.
if (ExpectAndConsume(tok::semi, diag::err_expected_semi_after, "@class"))
- return;
+ return 0;
- Actions.ParsedObjcClassDeclaration(CurScope,
- &ClassNames[0], ClassNames.size());
+ return Actions.ParsedObjcClassDeclaration(CurScope,
+ &ClassNames[0], ClassNames.size());
}
-void Parser::ParseObjCAtInterfaceDeclaration() {
+///
+/// objc-interface:
+/// objc-class-interface-attributes[opt] objc-class-interface
+/// objc-category-interface
+///
+/// objc-class-interface:
+/// '@' 'interface' identifier objc-superclass[opt]
+/// objc-protocol-refs[opt]
+/// objc-class-instance-variables[opt]
+/// objc-interface-decl-list
+/// @end
+///
+/// objc-category-interface:
+/// '@' 'interface' identifier '(' identifier[opt] ')'
+/// objc-protocol-refs[opt]
+/// objc-interface-decl-list
+/// @end
+///
+/// objc-superclass:
+/// ':' identifier
+///
+/// objc-class-interface-attributes:
+/// __attribute__((visibility("default")))
+/// __attribute__((visibility("hidden")))
+/// __attribute__((deprecated))
+/// __attribute__((unavailable))
+/// __attribute__((objc_exception)) - used by NSException on 64-bit
+///
+Parser::DeclTy *Parser::ParseObjCAtInterfaceDeclaration(
+ SourceLocation atLoc, AttributeList *attrList) {
+ assert(Tok.getIdentifierInfo()->getObjCKeywordID() == tok::objc_interface &&
+ "ParseObjCAtInterfaceDeclaration(): Expected @interface");
+ ConsumeToken(); // the "interface" identifier
+
+ if (Tok.getKind() != tok::identifier) {
+ Diag(Tok, diag::err_expected_ident); // missing class or category name.
+ return 0;
+ }
+ // We have a class or category name - consume it.
+ IdentifierInfo *nameId = Tok.getIdentifierInfo();
+ SourceLocation nameLoc = ConsumeToken();
+
+ if (Tok.getKind() == tok::l_paren) { // we have a category
+ SourceLocation lparenLoc = ConsumeParen();
+ SourceLocation categoryLoc, rparenLoc;
+ IdentifierInfo *categoryId = 0;
+
+ // OBJC2: The cateogry name is optional (not an error).
+ if (Tok.getKind() == tok::identifier) {
+ categoryId = Tok.getIdentifierInfo();
+ categoryLoc = ConsumeToken();
+ }
+ if (Tok.getKind() != tok::r_paren) {
+ Diag(Tok, diag::err_expected_rparen);
+ SkipUntil(tok::r_paren, false); // don't stop at ';'
+ return 0;
+ }
+ rparenLoc = ConsumeParen();
+ // Next, we need to check for any protocol references.
+ if (Tok.getKind() == tok::less) {
+ if (ParseObjCProtocolReferences())
+ return 0;
+ }
+ if (attrList) // categories don't support attributes.
+ Diag(Tok, diag::err_objc_no_attributes_on_category);
+
+ //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);
+ return 0;
+ }
+ ConsumeToken(); // the "end" identifier
+ return 0;
+ }
+ // Parse a class interface.
+ IdentifierInfo *superClassId = 0;
+ SourceLocation superClassLoc;
+
+ if (Tok.getKind() == tok::colon) { // a super class is specified.
+ ConsumeToken();
+ if (Tok.getKind() != tok::identifier) {
+ Diag(Tok, diag::err_expected_ident); // missing super class name.
+ return 0;
+ }
+ superClassId = Tok.getIdentifierInfo();
+ superClassLoc = ConsumeToken();
+ }
+ // Next, we need to check for any protocol references.
+ if (Tok.getKind() == tok::less) {
+ if (ParseObjCProtocolReferences())
+ return 0;
+ }
+ if (Tok.getKind() == tok::l_brace)
+ ParseObjCClassInstanceVariables();
+
+ //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);
+ return 0;
+ }
+ ConsumeToken(); // the "end" identifier
+ 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 declaration
+/// objc-interface-decl-list ';'
+///
+void Parser::ParseObjCInterfaceDeclList() {
assert(0 && "Unimp");
}
-void Parser::ParseObjCAtProtocolDeclaration() {
+
+/// objc-protocol-refs:
+/// '<' identifier-list '>'
+///
+bool Parser::ParseObjCProtocolReferences() {
+ assert(Tok.getKind() == tok::less && "expected <");
+
+ ConsumeToken(); // the "<"
+ llvm::SmallVector<IdentifierInfo *, 8> ProtocolRefs;
+
+ while (1) {
+ if (Tok.getKind() != tok::identifier) {
+ Diag(Tok, diag::err_expected_ident);
+ SkipUntil(tok::greater);
+ return true;
+ }
+ ProtocolRefs.push_back(Tok.getIdentifierInfo());
+ ConsumeToken();
+
+ if (Tok.getKind() != tok::comma)
+ break;
+ ConsumeToken();
+ }
+ // Consume the '>'.
+ return ExpectAndConsume(tok::greater, diag::err_expected_greater);
+}
+
+/// objc-class-instance-variables:
+/// '{' objc-instance-variable-decl-list[opt] '}'
+///
+/// objc-instance-variable-decl-list:
+/// objc-visibility-spec
+/// objc-instance-variable-decl ';'
+/// ';'
+/// objc-instance-variable-decl-list objc-visibility-spec
+/// objc-instance-variable-decl-list objc-instance-variable-decl ';'
+/// objc-instance-variable-decl-list ';'
+///
+/// objc-visibility-spec:
+/// @private
+/// @protected
+/// @public
+///
+/// objc-instance-variable-decl:
+/// struct-declaration
+///
+void Parser::ParseObjCClassInstanceVariables() {
assert(0 && "Unimp");
}
-void Parser::ParseObjCAtImplementationDeclaration() {
+
+/// objc-protocol-declaration:
+/// objc-protocol-definition
+/// objc-protocol-forward-reference
+///
+/// objc-protocol-definition:
+/// @protocol identifier
+/// objc-protocol-refs[opt]
+/// objc-methodprotolist
+/// @end
+///
+/// objc-protocol-forward-reference:
+/// @protocol identifier-list ';'
+///
+/// "@protocol identifier ;" should be resolved as "@protocol
+/// identifier-list ;": objc-methodprotolist may not start with a
+/// semicolon in the first alternative if objc-protocol-refs are omitted.
+
+Parser::DeclTy *Parser::ParseObjCAtProtocolDeclaration() {
+ assert(0 && "Unimp");
+ return 0;
+}
+
+/// objc-implementation:
+/// objc-class-implementation-prologue
+/// objc-category-implementation-prologue
+///
+/// objc-class-implementation-prologue:
+/// @implementation identifier objc-superclass[opt]
+/// objc-class-instance-variables[opt]
+///
+/// objc-category-implementation-prologue:
+/// @implementation identifier ( identifier )
+
+Parser::DeclTy *Parser::ParseObjCAtImplementationDeclaration() {
assert(0 && "Unimp");
+ return 0;
}
-void Parser::ParseObjCAtEndDeclaration() {
+Parser::DeclTy *Parser::ParseObjCAtEndDeclaration() {
assert(0 && "Unimp");
+ return 0;
}
-void Parser::ParseObjCAtAliasDeclaration() {
+Parser::DeclTy *Parser::ParseObjCAtAliasDeclaration() {
assert(0 && "Unimp");
+ return 0;
}
void Parser::ParseObjCInstanceMethodDeclaration() {
Modified: cfe/trunk/Parse/Parser.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Parse/Parser.cpp?rev=41200&r1=41199&r2=41200&view=diff
==============================================================================
--- cfe/trunk/Parse/Parser.cpp (original)
+++ cfe/trunk/Parse/Parser.cpp Mon Aug 20 16:31:48 2007
@@ -370,6 +370,13 @@
return Actions.ParsedFreeStandingDeclSpec(CurScope, DS);
}
+ // OBJC: This grammar hack allows prefix attributes on class interfaces.
+ if (Tok.getKind() == tok::at) {
+ SourceLocation AtLoc = ConsumeToken(); // the "@"
+ if (Tok.getIdentifierInfo()->getObjCKeywordID() == tok::objc_interface)
+ return ParseObjCAtInterfaceDeclaration(AtLoc, DS.getAttributes());
+ }
+
// Parse the first declarator.
Declarator DeclaratorInfo(DS, Declarator::FileContext);
ParseDeclarator(DeclaratorInfo);
Modified: cfe/trunk/include/clang/Basic/DiagnosticKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticKinds.def?rev=41200&r1=41199&r2=41200&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticKinds.def (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticKinds.def Mon Aug 20 16:31:48 2007
@@ -377,6 +377,12 @@
DIAG(err_matching, ERROR,
"to match this '%0'")
+/// Objective-C parser diagnostics
+DIAG(err_objc_no_attributes_on_category, ERROR,
+ "attributes may not be specified on a category")
+DIAG(err_objc_missing_end, ERROR,
+ "missing @end")
+
//===----------------------------------------------------------------------===//
// Semantic Analysis
//===----------------------------------------------------------------------===//
Modified: cfe/trunk/include/clang/Parse/Parser.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=41200&r1=41199&r2=41200&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Parser.h (original)
+++ cfe/trunk/include/clang/Parse/Parser.h Mon Aug 20 16:31:48 2007
@@ -254,13 +254,17 @@
void ParseAsmStringLiteral();
// Objective-C External Declarations
- void ParseObjCAtDirectives();
- void ParseObjCAtClassDeclaration(SourceLocation atLoc);
- void ParseObjCAtInterfaceDeclaration();
- void ParseObjCAtProtocolDeclaration();
- void ParseObjCAtImplementationDeclaration();
- void ParseObjCAtEndDeclaration();
- void ParseObjCAtAliasDeclaration();
+ DeclTy *ParseObjCAtDirectives();
+ DeclTy *ParseObjCAtClassDeclaration(SourceLocation atLoc);
+ DeclTy *ParseObjCAtInterfaceDeclaration(SourceLocation atLoc,
+ AttributeList *prefixAttrs = 0);
+ void ParseObjCClassInstanceVariables();
+ bool ParseObjCProtocolReferences();
+ void ParseObjCInterfaceDeclList();
+ DeclTy *ParseObjCAtProtocolDeclaration();
+ DeclTy *ParseObjCAtImplementationDeclaration();
+ DeclTy *ParseObjCAtEndDeclaration();
+ DeclTy *ParseObjCAtAliasDeclaration();
void ParseObjCInstanceMethodDeclaration();
void ParseObjCClassMethodDeclaration();
More information about the cfe-commits
mailing list