aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSteve Naroff <snaroff@apple.com>2007-09-05 23:30:30 +0000
committerSteve Naroff <snaroff@apple.com>2007-09-05 23:30:30 +0000
commitf28b264437053fb0deacc9ba02b18a0966f7290a (patch)
tree193d56c03b296ccdc9ca22991f980f57c5b17255
parenta65ff6c81f5b278000839988bb532114fd8c6797 (diff)
Start implementing Actions interface for ObjC classes, instance variables, and methods.
Lot's of small changes to the parser. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@41732 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--Parse/ParseDecl.cpp6
-rw-r--r--Parse/ParseObjc.cpp115
-rw-r--r--clang.xcodeproj/project.pbxproj2
-rw-r--r--include/clang/Parse/Action.h29
-rw-r--r--include/clang/Parse/DeclSpec.h17
-rw-r--r--include/clang/Parse/Parser.h14
6 files changed, 137 insertions, 46 deletions
diff --git a/Parse/ParseDecl.cpp b/Parse/ParseDecl.cpp
index 1db426a93f..dc9edc332c 100644
--- a/Parse/ParseDecl.cpp
+++ b/Parse/ParseDecl.cpp
@@ -406,8 +406,10 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS) {
else { // FIXME: restrict this to "id" and ObjC classnames.
DS.Range.setEnd(Tok.getLocation());
ConsumeToken(); // The identifier
- if (Tok.getKind() == tok::less)
- ParseObjCProtocolReferences();
+ if (Tok.getKind() == tok::less) {
+ llvm::SmallVector<IdentifierInfo *, 8> ProtocolRefs;
+ ParseObjCProtocolReferences(ProtocolRefs);
+ }
continue;
}
}
diff --git a/Parse/ParseObjc.cpp b/Parse/ParseObjc.cpp
index 21f59e32b7..39772a3d6a 100644
--- a/Parse/ParseObjc.cpp
+++ b/Parse/ParseObjc.cpp
@@ -147,13 +147,15 @@ Parser::DeclTy *Parser::ParseObjCAtInterfaceDeclaration(
rparenLoc = ConsumeParen();
// Next, we need to check for any protocol references.
if (Tok.getKind() == tok::less) {
- if (ParseObjCProtocolReferences())
+ llvm::SmallVector<IdentifierInfo *, 8> ProtocolRefs;
+ if (ParseObjCProtocolReferences(ProtocolRefs))
return 0;
}
if (attrList) // categories don't support attributes.
Diag(Tok, diag::err_objc_no_attributes_on_category);
- ParseObjCInterfaceDeclList(0/*FIXME*/);
+ llvm::SmallVector<DeclTy*, 64> MethodDecls;
+ ParseObjCInterfaceDeclList(0/*FIXME*/, MethodDecls);
// The @ sign was already consumed by ParseObjCInterfaceDeclList().
if (Tok.isObjCAtKeyword(tok::objc_end)) {
@@ -182,15 +184,21 @@ Parser::DeclTy *Parser::ParseObjCAtInterfaceDeclaration(
superClassLoc = ConsumeToken();
}
// Next, we need to check for any protocol references.
+ llvm::SmallVector<IdentifierInfo *, 8> ProtocolRefs;
if (Tok.getKind() == tok::less) {
- if (ParseObjCProtocolReferences())
+ if (ParseObjCProtocolReferences(ProtocolRefs))
return 0;
}
- // FIXME: add Actions.StartObjCClassInterface(nameId, superClassId, ...)
+ DeclTy *ClsType = Actions.ObjcStartClassInterface(atLoc, nameId, nameLoc,
+ superClassId, superClassLoc, &ProtocolRefs[0],
+ ProtocolRefs.size(), attrList);
+
+ llvm::SmallVector<DeclTy*, 32> IvarDecls;
if (Tok.getKind() == tok::l_brace)
- ParseObjCClassInstanceVariables(0/*FIXME*/);
+ ParseObjCClassInstanceVariables(ClsType, IvarDecls);
- ParseObjCInterfaceDeclList(0/*FIXME*/);
+ llvm::SmallVector<DeclTy*, 64> MethodDecls;
+ ParseObjCInterfaceDeclList(ClsType, MethodDecls);
// The @ sign was already consumed by ParseObjCInterfaceDeclList().
if (Tok.isObjCAtKeyword(tok::objc_end)) {
@@ -213,7 +221,9 @@ Parser::DeclTy *Parser::ParseObjCAtInterfaceDeclaration(
/// @required
/// @optional
///
-void Parser::ParseObjCInterfaceDeclList(DeclTy *interfaceDecl) {
+void Parser::ParseObjCInterfaceDeclList(
+ DeclTy *interfaceDecl, llvm::SmallVectorImpl<DeclTy*> &MethodDecls) {
+ DeclTy *IDecl = 0;
while (1) {
if (Tok.getKind() == tok::at) {
SourceLocation AtLoc = ConsumeToken(); // the "@"
@@ -236,17 +246,20 @@ void Parser::ParseObjCInterfaceDeclList(DeclTy *interfaceDecl) {
}
}
if (Tok.getKind() == tok::minus || Tok.getKind() == tok::plus) {
- ParseObjCMethodPrototype(true);
+ IDecl = ParseObjCMethodPrototype(true);
+ MethodDecls.push_back(IDecl);
continue;
}
if (Tok.getKind() == tok::semi)
ConsumeToken();
else if (Tok.getKind() == tok::eof)
return;
- else
+ else {
// FIXME: as the name implies, this rule allows function definitions.
// We could pass a flag or check for functions during semantic analysis.
- ParseDeclarationOrFunctionDefinition();
+ IDecl = ParseDeclarationOrFunctionDefinition();
+ MethodDecls.push_back(IDecl);
+ }
}
}
@@ -353,7 +366,7 @@ void Parser::ParseObjCPropertyDecl(DeclTy *interfaceDecl) {
/// objc-method-attributes: [OBJC2]
/// __attribute__((deprecated))
///
-void Parser::ParseObjCMethodPrototype(bool decl) {
+Parser::DeclTy *Parser::ParseObjCMethodPrototype(bool decl) {
assert((Tok.getKind() == tok::minus || Tok.getKind() == tok::plus) &&
"expected +/-");
@@ -361,15 +374,12 @@ void Parser::ParseObjCMethodPrototype(bool decl) {
SourceLocation methodLoc = ConsumeToken();
// FIXME: deal with "context sensitive" protocol qualifiers in prototypes
- ParseObjCMethodDecl(methodType, methodLoc);
+ DeclTy *MDecl = ParseObjCMethodDecl(methodType, methodLoc);
- // If attributes exist after the method, parse them.
- if (getLang().ObjC2 && Tok.getKind() == tok::kw___attribute)
- ParseAttributes();
-
if (decl)
// Consume the ';'.
ExpectAndConsume(tok::semi, diag::err_expected_semi_after, "method proto");
+ return MDecl;
}
/// objc-selector:
@@ -425,24 +435,26 @@ bool Parser::isObjCPropertyAttribute() {
/// objc-type-qualifier
/// objc-type-qualifiers objc-type-qualifier
///
-void Parser::ParseObjCTypeName() {
+Parser::TypeTy *Parser::ParseObjCTypeName() {
assert(Tok.getKind() == tok::l_paren && "expected (");
SourceLocation LParenLoc = ConsumeParen(), RParenLoc;
+ TypeTy *Ty;
while (isObjCTypeQualifier())
ConsumeToken();
if (isTypeSpecifierQualifier()) {
- //TypeTy *Ty = ParseTypeName();
- //assert(Ty && "Parser::ParseObjCTypeName(): missing type");
- ParseTypeName(); // FIXME: when sema support is added.
+ Ty = ParseTypeName();
+ // FIXME: back when Sema support is in place...
+ // assert(Ty && "Parser::ParseObjCTypeName(): missing type");
}
if (Tok.getKind() != tok::r_paren) {
MatchRHSPunctuation(tok::r_paren, LParenLoc);
- return;
+ return 0; // FIXME: decide how we want to handle this error...
}
RParenLoc = ConsumeParen();
+ return Ty;
}
/// objc-method-decl:
@@ -473,40 +485,52 @@ void Parser::ParseObjCTypeName() {
/// objc-keyword-attributes: [OBJC2]
/// __attribute__((unused))
///
-void Parser::ParseObjCMethodDecl(tok::TokenKind mType, SourceLocation mLoc) {
+Parser::DeclTy *Parser::ParseObjCMethodDecl(tok::TokenKind mType, SourceLocation mLoc) {
+ TypeTy *ReturnType = 0;
+
// Parse the return type.
if (Tok.getKind() == tok::l_paren)
- ParseObjCTypeName();
+ ReturnType = ParseObjCTypeName();
IdentifierInfo *selIdent = ParseObjCSelector();
+
+ llvm::SmallVector<ObjcKeywordInfo, 12> KeyInfo;
+ int KeySlot = 0;
if (Tok.getKind() == tok::colon) {
- IdentifierInfo *keywordSelector = selIdent;
+
while (1) {
+ KeyInfo[KeySlot].SelectorName = selIdent;
+
// Each iteration parses a single keyword argument.
if (Tok.getKind() != tok::colon) {
Diag(Tok, diag::err_expected_colon);
break;
}
- ConsumeToken(); // Eat the ':'.
+ KeyInfo[KeySlot].ColonLoc = ConsumeToken(); // Eat the ':'.
if (Tok.getKind() == tok::l_paren) // Parse the argument type.
- ParseObjCTypeName();
+ KeyInfo[KeySlot].TypeInfo = ParseObjCTypeName();
// If attributes exist before the argument name, parse them.
if (getLang().ObjC2 && Tok.getKind() == tok::kw___attribute)
- ParseAttributes();
+ KeyInfo[KeySlot].AttrList = ParseAttributes();
if (Tok.getKind() != tok::identifier) {
Diag(Tok, diag::err_expected_ident); // missing argument name.
break;
}
+ KeyInfo[KeySlot].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()
- keywordSelector = ParseObjCSelector();
- if (!keywordSelector && Tok.getKind() != tok::colon)
+ 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) {
@@ -522,20 +546,34 @@ void Parser::ParseObjCMethodDecl(tok::TokenKind mType, SourceLocation mLoc) {
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);
} else if (!selIdent) {
Diag(Tok, diag::err_expected_ident); // missing selector name.
}
- // FIXME: add Actions.BuildMethodSignature().
+ 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);
}
/// objc-protocol-refs:
/// '<' identifier-list '>'
///
-bool Parser::ParseObjCProtocolReferences() {
+bool Parser::ParseObjCProtocolReferences(
+ llvm::SmallVectorImpl<IdentifierInfo*> &ProtocolRefs) {
assert(Tok.getKind() == tok::less && "expected <");
ConsumeToken(); // the "<"
- llvm::SmallVector<IdentifierInfo *, 8> ProtocolRefs;
while (1) {
if (Tok.getKind() != tok::identifier) {
@@ -574,11 +612,11 @@ bool Parser::ParseObjCProtocolReferences() {
/// objc-instance-variable-decl:
/// struct-declaration
///
-void Parser::ParseObjCClassInstanceVariables(DeclTy *interfaceDecl) {
+void Parser::ParseObjCClassInstanceVariables(DeclTy *interfaceDecl,
+ llvm::SmallVectorImpl<DeclTy*> &IvarDecls) {
assert(Tok.getKind() == tok::l_brace && "expected {");
SourceLocation LBraceLoc = ConsumeBrace(); // the "{"
- llvm::SmallVector<DeclTy*, 32> IvarDecls;
// While we still have something to read, read the instance variables.
while (Tok.getKind() != tok::r_brace &&
@@ -685,10 +723,12 @@ Parser::DeclTy *Parser::ParseObjCAtProtocolDeclaration(SourceLocation AtLoc) {
}
// Last, and definitely not least, parse a protocol declaration.
if (Tok.getKind() == tok::less) {
- if (ParseObjCProtocolReferences())
+ llvm::SmallVector<IdentifierInfo *, 8> ProtocolRefs;
+ if (ParseObjCProtocolReferences(ProtocolRefs))
return 0;
}
- ParseObjCInterfaceDeclList(0/*FIXME*/);
+ llvm::SmallVector<DeclTy*, 64> MethodDecls;
+ ParseObjCInterfaceDeclList(0/*FIXME*/, MethodDecls);
// The @ sign was already consumed by ParseObjCInterfaceDeclList().
if (Tok.isObjCAtKeyword(tok::objc_end)) {
@@ -754,8 +794,9 @@ Parser::DeclTy *Parser::ParseObjCAtImplementationDeclaration(
}
ConsumeToken(); // Consume super class name
}
+ llvm::SmallVector<DeclTy*, 32> IvarDecls;
if (Tok.getKind() == tok::l_brace)
- ParseObjCClassInstanceVariables(0/*FIXME*/); // we have ivars
+ ParseObjCClassInstanceVariables(0/*FIXME*/, IvarDecls); // we have ivars
return 0;
}
diff --git a/clang.xcodeproj/project.pbxproj b/clang.xcodeproj/project.pbxproj
index c793c5f0cf..ceddc1fe51 100644
--- a/clang.xcodeproj/project.pbxproj
+++ b/clang.xcodeproj/project.pbxproj
@@ -211,7 +211,7 @@
3547129D0C88881300B3E1D5 /* PrettyPrinter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PrettyPrinter.h; path = clang/AST/PrettyPrinter.h; sourceTree = "<group>"; };
84D9A8870C1A57E100AC7ABC /* AttributeList.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = AttributeList.cpp; path = Parse/AttributeList.cpp; sourceTree = "<group>"; };
84D9A88B0C1A581300AC7ABC /* AttributeList.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = AttributeList.h; path = clang/Parse/AttributeList.h; sourceTree = "<group>"; };
- 8DD76F6C0486A84900D96B5E /* clang */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = "compiled.mach-o.executable"; path = clang; sourceTree = BUILT_PRODUCTS_DIR; };
+ 8DD76F6C0486A84900D96B5E /* clang */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = clang; sourceTree = BUILT_PRODUCTS_DIR; };
DE01DA480B12ADA300AC22CE /* PPCallbacks.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = PPCallbacks.h; sourceTree = "<group>"; };
DE06756B0C051CFE00EBBFD8 /* ParseExprCXX.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = ParseExprCXX.cpp; path = Parse/ParseExprCXX.cpp; sourceTree = "<group>"; };
DE06B73D0A8307640050E87E /* LangOptions.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = LangOptions.h; sourceTree = "<group>"; };
diff --git a/include/clang/Parse/Action.h b/include/clang/Parse/Action.h
index ec9a4d0dd2..20845ad9d6 100644
--- a/include/clang/Parse/Action.h
+++ b/include/clang/Parse/Action.h
@@ -21,6 +21,7 @@ namespace clang {
// Semantic.
class DeclSpec;
class Declarator;
+ class ObjcKeywordInfo;
class AttributeList;
// Parse.
class Scope;
@@ -430,7 +431,35 @@ public:
tok::TokenKind Kind) {
return 0;
}
+ //===----------------------- Obj-C Declarations -------------------------===//
+ virtual DeclTy *ObjcStartClassInterface(SourceLocation AtInterafceLoc,
+ IdentifierInfo *ClassName, SourceLocation ClassLoc,
+ IdentifierInfo *SuperName, SourceLocation SuperLoc,
+ IdentifierInfo **ProtocolNames, unsigned NumProtocols,
+ AttributeList *AttrList) {
+ return 0;
+ }
+ virtual void ObjCContinueClassInterface(SourceLocation InterfaceLoc) {
+ return;
+ }
+ virtual void ObjCStartCategoryInterface() {
+ return;
+ }
+ virtual void ObjCFinishInterface() {
+ return;
+ }
+ virtual DeclTy *ObjcBuildMethodDeclaration(
+ SourceLocation MethodLoc, tok::TokenKind MethodType, TypeTy *ReturnType,
+ ObjcKeywordInfo *Keywords, unsigned NumKeywords, AttributeList *attrs) {
+ return 0;
+ }
+ virtual DeclTy *ObjcBuildMethodDeclaration(
+ SourceLocation MethodLoc, tok::TokenKind MethodType, TypeTy *ReturnType,
+ IdentifierInfo *SelectorName, AttributeList *attrs) {
+ return 0;
+ }
+
//===----------------------- Obj-C Expressions --------------------------===//
virtual ExprResult ParseObjCStringLiteral(ExprTy *string) {
return 0;
diff --git a/include/clang/Parse/DeclSpec.h b/include/clang/Parse/DeclSpec.h
index 6a15290072..de22360120 100644
--- a/include/clang/Parse/DeclSpec.h
+++ b/include/clang/Parse/DeclSpec.h
@@ -562,7 +562,24 @@ public:
bool getInvalidType() { return InvalidType; }
};
+struct ObjcKeywordInfo {
+ IdentifierInfo *SelectorName; // optional
+ SourceLocation SelectorLoc;
+ SourceLocation ColonLoc;
+ Action::TypeTy *TypeInfo; // optional
+ bool InvalidType;
+ IdentifierInfo *ArgumentName;
+ AttributeList *AttrList;
+ ObjcKeywordInfo() {}
+ ObjcKeywordInfo(IdentifierInfo *selName, SourceLocation sLoc,
+ SourceLocation cLoc, Action::TypeTy *tInfo,
+ IdentifierInfo *argName, AttributeList *aList)
+ : SelectorName(selName), SelectorLoc(sLoc), ColonLoc(cLoc), TypeInfo(tInfo),
+ ArgumentName(argName), AttrList(aList) {
+ }
+};
+
} // end namespace clang
#endif
diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h
index f05a2ec5b5..c49d242ab5 100644
--- a/include/clang/Parse/Parser.h
+++ b/include/clang/Parse/Parser.h
@@ -258,9 +258,11 @@ private:
DeclTy *ParseObjCAtClassDeclaration(SourceLocation atLoc);
DeclTy *ParseObjCAtInterfaceDeclaration(SourceLocation atLoc,
AttributeList *prefixAttrs = 0);
- void ParseObjCClassInstanceVariables(DeclTy *interfaceDecl);
- bool ParseObjCProtocolReferences();
- void ParseObjCInterfaceDeclList(DeclTy *interfaceDecl);
+ void ParseObjCClassInstanceVariables(DeclTy *interfaceDecl,
+ llvm::SmallVectorImpl<DeclTy*> &IvarDecls);
+ bool ParseObjCProtocolReferences(llvm::SmallVectorImpl<IdentifierInfo*> &);
+ void ParseObjCInterfaceDeclList(DeclTy *interfaceDecl,
+ llvm::SmallVectorImpl<DeclTy*> &MethodDecls);
DeclTy *ParseObjCAtProtocolDeclaration(SourceLocation atLoc);
DeclTy *ParseObjCAtImplementationDeclaration(SourceLocation atLoc);
DeclTy *ParseObjCAtEndDeclaration(SourceLocation atLoc);
@@ -284,10 +286,10 @@ private:
IdentifierInfo *ObjcPropertyAttrs[objc_NumAttrs];
bool isObjCPropertyAttribute();
- void ParseObjCTypeName();
+ TypeTy *ParseObjCTypeName();
void ParseObjCMethodRequirement();
- void ParseObjCMethodPrototype(bool decl);
- void ParseObjCMethodDecl(tok::TokenKind mType, SourceLocation mLoc);
+ DeclTy *ParseObjCMethodPrototype(bool decl);
+ DeclTy *ParseObjCMethodDecl(tok::TokenKind mType, SourceLocation mLoc);
void ParseObjCPropertyAttribute(DeclTy *interfaceDecl);
void ParseObjCPropertyDecl(DeclTy *interfaceDecl);