From: Steve Naroff Date: Mon, 17 Sep 2007 20:25:27 +0000 (+0000) Subject: - Refactored ObjcKeywordInfo into ObjcKeywordInfo, ObjcKeywordDecl, and ObjcKeywordMe... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=37387c932855c6d58d70bdd705cd3a9fdcd2a931;p=clang - Refactored ObjcKeywordInfo into ObjcKeywordInfo, ObjcKeywordDecl, and ObjcKeywordMessage. - Removed helper ObjcGetSelectorInfo(), moving the code directly into ObjcBuildMethodDeclaration(). - Many refinements to ParseObjCMessageExpression(). - Add ActOnMessageExpression(). Next step, finish the message actions and (finally) create/instantiate an ObjcMessageExpr AST. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@42050 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/Parse/ParseObjc.cpp b/Parse/ParseObjc.cpp index e396f375e7..d61d621093 100644 --- a/Parse/ParseObjc.cpp +++ b/Parse/ParseObjc.cpp @@ -486,12 +486,12 @@ Parser::DeclTy *Parser::ParseObjCMethodDecl(tok::TokenKind mType, ReturnType = ParseObjCTypeName(); IdentifierInfo *selIdent = ParseObjCSelector(); - llvm::SmallVector KeyInfo; + llvm::SmallVector KeyInfo; if (Tok.getKind() == tok::colon) { while (1) { - ObjcKeywordInfo KeyInfoDecl; + ObjcKeywordDecl KeyInfoDecl; KeyInfoDecl.SelectorName = selIdent; // Each iteration parses a single keyword argument. @@ -514,11 +514,11 @@ Parser::DeclTy *Parser::ParseObjCMethodDecl(tok::TokenKind mType, 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() - + // Rather than call out to the actions, package up the info locally, + // like we do for Declarator. KeyInfo.push_back(KeyInfoDecl); + + // Check for another keyword selector. selIdent = ParseObjCSelector(); if (!selIdent && Tok.getKind() != tok::colon) break; @@ -984,28 +984,52 @@ Parser::ExprResult Parser::ParseObjCExpression() { Parser::ExprResult Parser::ParseObjCMessageExpression() { assert(Tok.getKind() == tok::l_square && "'[' expected"); SourceLocation Loc = ConsumeBracket(); // consume '[' + IdentifierInfo *ReceiverName = 0; + ExprTy *ReceiverExpr = 0; // Parse receiver if (Tok.getKind() == tok::identifier && - Actions.isTypeName(*Tok.getIdentifierInfo(), CurScope)) + Actions.isTypeName(*Tok.getIdentifierInfo(), CurScope)) { + ReceiverName = Tok.getIdentifierInfo(); ConsumeToken(); - else - ParseAssignmentExpression(); + } else { + ExprResult Res = ParseAssignmentExpression(); + if (Res.isInvalid) { + SkipUntil(tok::identifier); + return Res; + } + ReceiverExpr = Res.Val; + } // Parse objc-selector IdentifierInfo *selIdent = ParseObjCSelector(); + llvm::SmallVector KeyInfo; if (Tok.getKind() == tok::colon) { while (1) { // Each iteration parses a single keyword argument. + ObjcKeywordMessage KeyInfoMess; + KeyInfoMess.SelectorName = selIdent; + if (Tok.getKind() != tok::colon) { Diag(Tok, diag::err_expected_colon); SkipUntil(tok::semi); - return 0; + return true; } - ConsumeToken(); // Eat the ':'. + KeyInfoMess.ColonLoc = ConsumeToken(); // Eat the ':'. /// Parse the expression after ':' - ParseAssignmentExpression(); - IdentifierInfo *keywordSelector = ParseObjCSelector(); + ExprResult Res = ParseAssignmentExpression(); + if (Res.isInvalid) { + SkipUntil(tok::identifier); + return Res; + } + // We have a valid expression. + KeyInfoMess.KeywordExpr = Res.Val; + + // Rather than call out to the actions, package up the info locally, + // like we do for Declarator. + KeyInfo.push_back(KeyInfoMess); - if (!keywordSelector && Tok.getKind() != tok::colon) + // Check for another keyword selector. + selIdent = ParseObjCSelector(); + if (!selIdent && Tok.getKind() != tok::colon) break; // We have a selector or a colon, continue parsing. } @@ -1026,7 +1050,12 @@ Parser::ExprResult Parser::ParseObjCMessageExpression() { return 0; } ConsumeBracket(); // consume ']' - return 0; // FIXME: return a message expr AST! + + if (ReceiverName) + return Actions.ActOnMessageExpression(ReceiverName, + &KeyInfo[0], KeyInfo.size()); + return Actions.ActOnMessageExpression(ReceiverExpr, + &KeyInfo[0], KeyInfo.size()); } Parser::ExprResult Parser::ParseObjCStringLiteral() { diff --git a/Sema/Sema.h b/Sema/Sema.h index 95086534b5..c1d3a3a05a 100644 --- a/Sema/Sema.h +++ b/Sema/Sema.h @@ -366,7 +366,7 @@ public: DeclTy **allMethods, unsigned allNum); virtual DeclTy *ObjcBuildMethodDeclaration(SourceLocation MethodLoc, tok::TokenKind MethodType, TypeTy *ReturnType, - ObjcKeywordInfo *Keywords, unsigned NumKeywords, + ObjcKeywordDecl *Keywords, unsigned NumKeywords, AttributeList *AttrList); virtual DeclTy *ObjcBuildMethodDeclaration(SourceLocation MethodLoc, tok::TokenKind MethodType, TypeTy *ReturnType, diff --git a/Sema/SemaDecl.cpp b/Sema/SemaDecl.cpp index 22a7c0418d..051ba7665b 100644 --- a/Sema/SemaDecl.cpp +++ b/Sema/SemaDecl.cpp @@ -1239,41 +1239,33 @@ void Sema::ObjcAddMethodsToClass(DeclTy *ClassDecl, return; } -/// Build objective-c style method name. -static SelectorInfo & - ObjcGetSelectorInfo(ObjcKeywordInfo* KeyInfo, unsigned numKeyInfo, - ASTContext &Context) -{ +Sema::DeclTy *Sema::ObjcBuildMethodDeclaration(SourceLocation MethodLoc, + tok::TokenKind MethodType, TypeTy *ReturnType, + ObjcKeywordDecl *Keywords, unsigned NumKeywords, + AttributeList *AttrList) { + assert(NumKeywords && "Selector must be specified"); + + // Derive the selector name from the keyword declarations. int len=0; char *methodName; - for (unsigned int i = 0; i < numKeyInfo; i++) { - IdentifierInfo *selectorName = KeyInfo[i].SelectorName; - if (selectorName) - len += strlen(selectorName->getName()); + for (unsigned int i = 0; i < NumKeywords; i++) { + if (Keywords[i].SelectorName) + len += strlen(Keywords[i].SelectorName->getName()); len++; } methodName = (char *) alloca (len + 1); methodName[0] = '\0'; - for (unsigned int i = 0; i < numKeyInfo; i++) { - IdentifierInfo *selectorName = KeyInfo[i].SelectorName; - if (selectorName) - strcat(methodName, selectorName->getName()); + for (unsigned int i = 0; i < NumKeywords; i++) { + if (Keywords[i].SelectorName) + strcat(methodName, Keywords[i].SelectorName->getName()); strcat(methodName, ":"); } - return Context.getSelectorInfo(methodName, methodName+len); -} + SelectorInfo &SelName = Context.getSelectorInfo(methodName, methodName+len); - -Sema::DeclTy *Sema::ObjcBuildMethodDeclaration(SourceLocation MethodLoc, - tok::TokenKind MethodType, TypeTy *ReturnType, - ObjcKeywordInfo *Keywords, unsigned NumKeywords, - AttributeList *AttrList) { - assert(NumKeywords && "Selector must be specified"); - SelectorInfo &SelName = ObjcGetSelectorInfo(Keywords, NumKeywords, Context); llvm::SmallVector Params; for (unsigned i = 0; i < NumKeywords; i++) { - ObjcKeywordInfo *arg = &Keywords[i]; + ObjcKeywordDecl *arg = &Keywords[i]; // FIXME: arg->AttrList must be stored too! ParmVarDecl* Param = new ParmVarDecl(arg->ColonLoc, arg->ArgumentName, QualType::getFromOpaquePtr(arg->TypeInfo), @@ -1284,9 +1276,9 @@ Sema::DeclTy *Sema::ObjcBuildMethodDeclaration(SourceLocation MethodLoc, Params.push_back(Param); } QualType resultDeclType = QualType::getFromOpaquePtr(ReturnType); - ObjcMethodDecl* ObjcMethod = new ObjcMethodDecl(MethodLoc, - SelName, resultDeclType, - 0, -1, AttrList, MethodType == tok::minus); + ObjcMethodDecl* ObjcMethod; + ObjcMethod = new ObjcMethodDecl(MethodLoc, SelName, resultDeclType, + 0, -1, AttrList, MethodType == tok::minus); ObjcMethod->setMethodParams(&Params[0], NumKeywords); return ObjcMethod; } diff --git a/clang.xcodeproj/project.pbxproj b/clang.xcodeproj/project.pbxproj index b10e99d777..6ccef0836f 100644 --- a/clang.xcodeproj/project.pbxproj +++ b/clang.xcodeproj/project.pbxproj @@ -708,7 +708,6 @@ 08FB7793FE84155DC02AAC07 /* Project object */ = { isa = PBXProject; buildConfigurationList = 1DEB923508733DC60010E9CD /* Build configuration list for PBXProject "clang" */; - compatibilityVersion = "Xcode 2.4"; hasScannedForEncodings = 1; mainGroup = 08FB7794FE84155DC02AAC07 /* clang */; projectDirPath = ""; diff --git a/include/clang/Parse/Action.h b/include/clang/Parse/Action.h index e16d3f0fe9..2d7e8f452c 100644 --- a/include/clang/Parse/Action.h +++ b/include/clang/Parse/Action.h @@ -21,7 +21,8 @@ namespace clang { // Semantic. class DeclSpec; class Declarator; - struct ObjcKeywordInfo; + struct ObjcKeywordDecl; + struct ObjcKeywordMessage; class AttributeList; // Parse. class Scope; @@ -145,12 +146,6 @@ public: return 0; } - virtual DeclTy *ObjcClassDeclaration(Scope *S, SourceLocation AtClassLoc, - IdentifierInfo **IdentList, - unsigned NumElts) { - return 0; - } - //===--------------------------------------------------------------------===// // Type Parsing Callbacks. //===--------------------------------------------------------------------===// @@ -455,7 +450,7 @@ public: } virtual DeclTy *ObjcBuildMethodDeclaration( SourceLocation MethodLoc, tok::TokenKind MethodType, TypeTy *ReturnType, - ObjcKeywordInfo *Keywords, unsigned NumKeywords, + ObjcKeywordDecl *Keywords, unsigned NumKeywords, AttributeList *AttrList) { return 0; } @@ -464,6 +459,21 @@ public: IdentifierInfo *SelectorName, AttributeList *AttrList) { return 0; } + // This actions handles keyword message to classes. + virtual DeclTy *ActOnMessageExpression(IdentifierInfo *receivingClassName, + ObjcKeywordMessage *Keywords, unsigned NumKeywords) { + return 0; + } + // This action handles keyword messages to instances. + virtual DeclTy *ActOnMessageExpression(ExprTy *receiver, + ObjcKeywordMessage *Keywords, unsigned NumKeywords) { + return 0; + } + virtual DeclTy *ObjcClassDeclaration(Scope *S, SourceLocation AtClassLoc, + IdentifierInfo **IdentList, + unsigned NumElts) { + return 0; + } virtual void ObjCStartCategoryInterface() { // FIXME return; } diff --git a/include/clang/Parse/DeclSpec.h b/include/clang/Parse/DeclSpec.h index de22360120..bf197186ba 100644 --- a/include/clang/Parse/DeclSpec.h +++ b/include/clang/Parse/DeclSpec.h @@ -566,20 +566,37 @@ struct ObjcKeywordInfo { IdentifierInfo *SelectorName; // optional SourceLocation SelectorLoc; SourceLocation ColonLoc; + + ObjcKeywordInfo() {} + ObjcKeywordInfo(IdentifierInfo *selName, SourceLocation sLoc, + SourceLocation cLoc) + : SelectorName(selName), SelectorLoc(sLoc), ColonLoc(cLoc) {} +}; + +struct ObjcKeywordDecl : ObjcKeywordInfo { Action::TypeTy *TypeInfo; // optional - bool InvalidType; IdentifierInfo *ArgumentName; AttributeList *AttrList; + bool InvalidType; // FIXME: is this used? - ObjcKeywordInfo() {} - ObjcKeywordInfo(IdentifierInfo *selName, SourceLocation sLoc, + ObjcKeywordDecl() {} + ObjcKeywordDecl(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) { + : ObjcKeywordInfo(selName, sLoc, cLoc), + TypeInfo(tInfo), ArgumentName(argName), AttrList(aList) { } }; + +struct ObjcKeywordMessage : ObjcKeywordInfo { + Action::ExprTy *KeywordExpr; + + ObjcKeywordMessage() {} + ObjcKeywordMessage(IdentifierInfo *selName, SourceLocation sLoc, + SourceLocation cLoc, Action::ExprTy *expr) + : ObjcKeywordInfo(selName, sLoc, cLoc), KeywordExpr(expr) {} +}; -} // end namespace clang +} // end namespace clang #endif