diff options
-rw-r--r-- | AST/Expr.cpp | 74 | ||||
-rw-r--r-- | Lex/IdentifierTable.cpp | 23 | ||||
-rw-r--r-- | Parse/ParseObjc.cpp | 130 | ||||
-rw-r--r-- | Sema/ASTStreamer.cpp | 2 | ||||
-rw-r--r-- | Sema/Sema.h | 43 | ||||
-rw-r--r-- | Sema/SemaDecl.cpp | 64 | ||||
-rw-r--r-- | Sema/SemaExpr.cpp | 83 | ||||
-rw-r--r-- | include/clang/AST/ASTContext.h | 11 | ||||
-rw-r--r-- | include/clang/AST/Decl.h | 11 | ||||
-rw-r--r-- | include/clang/AST/Expr.h | 48 | ||||
-rw-r--r-- | include/clang/Lex/IdentifierTable.h | 63 | ||||
-rw-r--r-- | include/clang/Lex/Preprocessor.h | 13 | ||||
-rw-r--r-- | include/clang/Parse/Action.h | 61 | ||||
-rw-r--r-- | include/clang/Parse/DeclSpec.h | 20 |
14 files changed, 328 insertions, 318 deletions
diff --git a/AST/Expr.cpp b/AST/Expr.cpp index 0b1c7994ff..312d209e2d 100644 --- a/AST/Expr.cpp +++ b/AST/Expr.cpp @@ -15,8 +15,6 @@ #include "clang/AST/ASTContext.h" #include "clang/AST/StmtVisitor.h" #include "clang/Lex/IdentifierTable.h" -// is this bad layering? I (snaroff) don't think so. Want Chris to weigh in. -#include "clang/Parse/DeclSpec.h" using namespace clang; //===----------------------------------------------------------------------===// @@ -870,51 +868,53 @@ unsigned OCUVectorElementExpr::getEncodedElementAccess() const { return Result; } -// constructor for unary messages. -ObjCMessageExpr::ObjCMessageExpr( - IdentifierInfo *clsName, IdentifierInfo &methName, QualType retType, - SourceLocation LBrac, SourceLocation RBrac) - : Expr(ObjCMessageExprClass, retType), Selector(methName) { - ClassName = clsName; - LBracloc = LBrac; - RBracloc = RBrac; -} - -ObjCMessageExpr::ObjCMessageExpr( - Expr *fn, IdentifierInfo &methName, QualType retType, - SourceLocation LBrac, SourceLocation RBrac) - : Expr(ObjCMessageExprClass, retType), Selector(methName), ClassName(0) { - SubExprs = new Expr*[1]; - SubExprs[RECEIVER] = fn; - LBracloc = LBrac; - RBracloc = RBrac; -} - -// constructor for keyword messages. -ObjCMessageExpr::ObjCMessageExpr( - Expr *fn, IdentifierInfo &selInfo, ObjcKeywordMessage *keys, unsigned numargs, - QualType retType, SourceLocation LBrac, SourceLocation RBrac) +// constructor for instance messages. +ObjCMessageExpr::ObjCMessageExpr(Expr *receiver, SelectorInfo *selInfo, + QualType retType, SourceLocation LBrac, SourceLocation RBrac, + Expr **ArgExprs) : Expr(ObjCMessageExprClass, retType), Selector(selInfo), ClassName(0) { - SubExprs = new Expr*[numargs+1]; - SubExprs[RECEIVER] = fn; - for (unsigned i = 0; i != numargs; ++i) - SubExprs[i+ARGS_START] = static_cast<Expr *>(keys[i].KeywordExpr); + unsigned numArgs = selInfo->getNumArgs(); + SubExprs = new Expr*[numArgs+1]; + SubExprs[RECEIVER] = receiver; + if (numArgs) { + for (unsigned i = 0; i != numArgs; ++i) + SubExprs[i+ARGS_START] = static_cast<Expr *>(ArgExprs[i]); + } LBracloc = LBrac; RBracloc = RBrac; } -ObjCMessageExpr::ObjCMessageExpr( - IdentifierInfo *clsName, IdentifierInfo &selInfo, ObjcKeywordMessage *keys, - unsigned numargs, QualType retType, SourceLocation LBrac, SourceLocation RBrac) +// constructor for class messages. +// FIXME: clsName should be typed to ObjCInterfaceType +ObjCMessageExpr::ObjCMessageExpr(IdentifierInfo *clsName, SelectorInfo *selInfo, + QualType retType, SourceLocation LBrac, SourceLocation RBrac, + Expr **ArgExprs) : Expr(ObjCMessageExprClass, retType), Selector(selInfo), ClassName(clsName) { - SubExprs = new Expr*[numargs+1]; + unsigned numArgs = selInfo->getNumArgs(); + SubExprs = new Expr*[numArgs+1]; SubExprs[RECEIVER] = 0; - for (unsigned i = 0; i != numargs; ++i) - SubExprs[i+ARGS_START] = static_cast<Expr *>(keys[i].KeywordExpr); + if (numArgs) { + for (unsigned i = 0; i != numArgs; ++i) + SubExprs[i+ARGS_START] = static_cast<Expr *>(ArgExprs[i]); + } LBracloc = LBrac; RBracloc = RBrac; } +// The following 3 methods are defined here (instead of Epxr.h) to avoid +// importing "IdentifierTable.h" into the header. +unsigned ObjCMessageExpr::getNumArgs() const { return Selector->getNumArgs(); } + +/// getArg - Return the specified argument. +Expr *ObjCMessageExpr::getArg(unsigned Arg) { + assert(Arg < Selector->getNumArgs() && "Arg access out of range!"); + return SubExprs[Arg+ARGS_START]; +} +const Expr *ObjCMessageExpr::getArg(unsigned Arg) const { + assert(Arg < Selector->getNumArgs() && "Arg access out of range!"); + return SubExprs[Arg+ARGS_START]; +} + //===----------------------------------------------------------------------===// // Child Iterators for iterating over subexpressions/substatements @@ -1090,6 +1090,6 @@ Stmt::child_iterator ObjCMessageExpr::child_begin() { return reinterpret_cast<Stmt**>(&SubExprs[0]); } Stmt::child_iterator ObjCMessageExpr::child_end() { - return reinterpret_cast<Stmt**>(&SubExprs[NumArgs+ARGS_START]); + return reinterpret_cast<Stmt**>(&SubExprs[getNumArgs()+ARGS_START]); } diff --git a/Lex/IdentifierTable.cpp b/Lex/IdentifierTable.cpp index d3faeb58db..6ab0ef1a69 100644 --- a/Lex/IdentifierTable.cpp +++ b/Lex/IdentifierTable.cpp @@ -33,6 +33,28 @@ tok::ObjCKeywordKind Token::getObjCKeywordID() const { return specId ? specId->getObjCKeywordID() : tok::objc_not_keyword; } +char *SelectorInfo::getName(llvm::SmallString<128> methodName) { + int len=0; + methodName[0] = '\0'; + if (NumArgs) { + keyword_iterator KeyIter = keyword_begin(); + for (unsigned int i = 0; i < NumArgs; i++) { + if (KeyIter[i]) { + methodName += KeyIter[i]->getName(); + len += strlen(KeyIter[i]->getName()); + } + methodName += ":"; + len++; + } + } else { + IdentifierInfo **UnaryInfo = reinterpret_cast<IdentifierInfo **>(this+1); + methodName += UnaryInfo[0]->getName(); + len += strlen(UnaryInfo[0]->getName()); + } + methodName[len] = '\0'; + return &methodName[0]; +} + //===----------------------------------------------------------------------===// // IdentifierInfo Implementation //===----------------------------------------------------------------------===// @@ -209,3 +231,4 @@ void IdentifierTable::PrintStats() const { // Compute statistics about the memory allocated for identifiers. HashTable.getAllocator().PrintStats(); } + diff --git a/Parse/ParseObjc.cpp b/Parse/ParseObjc.cpp index eddbb4a254..16434cdcdd 100644 --- a/Parse/ParseObjc.cpp +++ b/Parse/ParseObjc.cpp @@ -463,6 +463,52 @@ Parser::TypeTy *Parser::ParseObjCTypeName() { return Ty; } +static SelectorInfo *ObjcGetUnarySelectorInfo( + IdentifierInfo *unarySel, + llvm::FoldingSet<SelectorInfo> &SelTab) +{ + // Unique selector, to guarantee there is one per name. + llvm::SmallVector<IdentifierInfo *, 1> IIV; + llvm::FoldingSetNodeID ID; + + IIV.push_back(unarySel); + SelectorInfo::Profile(ID, &IIV[0], 0); + + void *InsertPos = 0; + if (SelectorInfo *SI = SelTab.FindNodeOrInsertPos(ID, InsertPos)) + return SI; + + // SelectorInfo objects are not allocated with new because they have a + // variable size array (for parameter types) at the end of them. + SelectorInfo *SI = + (SelectorInfo*)malloc(sizeof(SelectorInfo) + sizeof(IdentifierInfo *)); + new (SI) SelectorInfo(IIV[0]); + SelTab.InsertNode(SI, InsertPos); + return SI; +} + +static SelectorInfo *ObjcGetKeywordSelectorInfo( + llvm::SmallVectorImpl<IdentifierInfo *> &IIV, + llvm::FoldingSet<SelectorInfo> &SelTab) +{ + // Unique selector, to guarantee there is one per name. + llvm::FoldingSetNodeID ID; + SelectorInfo::Profile(ID, &IIV[0], IIV.size()); + + void *InsertPos = 0; + if (SelectorInfo *SI = SelTab.FindNodeOrInsertPos(ID, InsertPos)) + return SI; + + // SelectorInfo objects are not allocated with new because they have a + // variable size array (for parameter types) at the end of them. + SelectorInfo *SI = + (SelectorInfo*)malloc(sizeof(SelectorInfo) + + IIV.size()*sizeof(IdentifierInfo *)); + new (SI) SelectorInfo(IIV.size(), &IIV[0]); + SelTab.InsertNode(SI, InsertPos); + return SI; +} + /// objc-method-decl: /// objc-selector /// objc-keyword-selector objc-parmlist[opt] @@ -491,9 +537,10 @@ Parser::TypeTy *Parser::ParseObjCTypeName() { /// objc-keyword-attributes: [OBJC2] /// __attribute__((unused)) /// -Parser::DeclTy *Parser::ParseObjCMethodDecl(tok::TokenKind mType, SourceLocation mLoc, - tok::ObjCKeywordKind MethodImplKind) { - +Parser::DeclTy *Parser::ParseObjCMethodDecl(tok::TokenKind mType, + SourceLocation mLoc, + tok::ObjCKeywordKind MethodImplKind) +{ TypeTy *ReturnType = 0; AttributeList *methodAttrs = 0; @@ -502,38 +549,39 @@ Parser::DeclTy *Parser::ParseObjCMethodDecl(tok::TokenKind mType, SourceLocation ReturnType = ParseObjCTypeName(); IdentifierInfo *selIdent = ParseObjCSelector(); - llvm::SmallVector<ObjcKeywordDecl, 12> KeyInfo; - + llvm::SmallVector<IdentifierInfo *, 12> KeyIdents; + llvm::SmallVector<Action::TypeTy *, 12> KeyTypes; + llvm::SmallVector<IdentifierInfo *, 12> ArgNames; + if (Tok.getKind() == tok::colon) { + Action::TypeTy *TypeInfo; while (1) { - ObjcKeywordDecl KeyInfoDecl; - KeyInfoDecl.SelectorName = selIdent; + KeyIdents.push_back(selIdent); // Each iteration parses a single keyword argument. if (Tok.getKind() != tok::colon) { Diag(Tok, diag::err_expected_colon); break; } - KeyInfoDecl.ColonLoc = ConsumeToken(); // Eat the ':'. + ConsumeToken(); // Eat the ':'. if (Tok.getKind() == tok::l_paren) // Parse the argument type. - KeyInfoDecl.TypeInfo = ParseObjCTypeName(); - + TypeInfo = ParseObjCTypeName(); + else + TypeInfo = 0; + KeyTypes.push_back(TypeInfo); + // If attributes exist before the argument name, parse them. if (getLang().ObjC2 && Tok.getKind() == tok::kw___attribute) - KeyInfoDecl.AttrList = ParseAttributes(); + ParseAttributes(); // FIXME: pass attributes through. if (Tok.getKind() != tok::identifier) { Diag(Tok, diag::err_expected_ident); // missing argument name. break; } - KeyInfoDecl.ArgumentName = Tok.getIdentifierInfo(); + ArgNames.push_back(Tok.getIdentifierInfo()); ConsumeToken(); // Eat the identifier. - // 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) @@ -558,9 +606,11 @@ Parser::DeclTy *Parser::ParseObjCMethodDecl(tok::TokenKind mType, SourceLocation // If attributes exist after the method, parse them. if (getLang().ObjC2 && Tok.getKind() == tok::kw___attribute) methodAttrs = ParseAttributes(); - return Actions.ObjcBuildMethodDeclaration(mLoc, mType, - ReturnType, - &KeyInfo[0], KeyInfo.size(), + + SelectorInfo *SI = ObjcGetKeywordSelectorInfo(KeyIdents, + PP.getSelectorTable()); + return Actions.ObjcBuildMethodDeclaration(mLoc, mType, ReturnType, SI, + &KeyTypes[0], &ArgNames[0], methodAttrs, MethodImplKind); } else if (!selIdent) { Diag(Tok, diag::err_expected_ident); // missing selector name. @@ -569,9 +619,9 @@ Parser::DeclTy *Parser::ParseObjCMethodDecl(tok::TokenKind mType, SourceLocation if (getLang().ObjC2 && Tok.getKind() == tok::kw___attribute) methodAttrs = ParseAttributes(); - return Actions.ObjcBuildMethodDeclaration(mLoc, mType, ReturnType, - selIdent, methodAttrs, - MethodImplKind); + SelectorInfo *SI = ObjcGetUnarySelectorInfo(selIdent, PP.getSelectorTable()); + return Actions.ObjcBuildMethodDeclaration(mLoc, mType, ReturnType, SI, + 0, 0, methodAttrs, MethodImplKind); } /// objc-protocol-refs: @@ -1107,19 +1157,21 @@ Parser::ExprResult Parser::ParseObjCMessageExpression() { } // Parse objc-selector IdentifierInfo *selIdent = ParseObjCSelector(); - llvm::SmallVector<ObjcKeywordMessage, 12> KeyInfo; + + llvm::SmallVector<IdentifierInfo *, 12> KeyIdents; + llvm::SmallVector<Action::ExprTy *, 12> KeyExprs; + if (Tok.getKind() == tok::colon) { while (1) { // Each iteration parses a single keyword argument. - ObjcKeywordMessage KeyInfoMess; - KeyInfoMess.SelectorName = selIdent; + KeyIdents.push_back(selIdent); if (Tok.getKind() != tok::colon) { Diag(Tok, diag::err_expected_colon); SkipUntil(tok::semi); return true; } - KeyInfoMess.ColonLoc = ConsumeToken(); // Eat the ':'. + ConsumeToken(); // Eat the ':'. /// Parse the expression after ':' ExprResult Res = ParseAssignmentExpression(); if (Res.isInvalid) { @@ -1127,11 +1179,7 @@ Parser::ExprResult Parser::ParseObjCMessageExpression() { 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); + KeyExprs.push_back(Res.Val); // Check for another keyword selector. selIdent = ParseObjCSelector(); @@ -1157,20 +1205,22 @@ Parser::ExprResult Parser::ParseObjCMessageExpression() { } SourceLocation RBracloc = ConsumeBracket(); // consume ']' - if (KeyInfo.size()) { + if (KeyIdents.size()) { + SelectorInfo *SI = ObjcGetKeywordSelectorInfo(KeyIdents, + PP.getSelectorTable()); // We've just parsed a keyword message. if (ReceiverName) - return Actions.ActOnKeywordMessage(ReceiverName, - &KeyInfo[0], KeyInfo.size(), - LBracloc, RBracloc); - return Actions.ActOnKeywordMessage(ReceiverExpr, - &KeyInfo[0], KeyInfo.size(), - LBracloc, RBracloc); + return Actions.ActOnClassMessage(ReceiverName, SI, LBracloc, RBracloc, + &KeyExprs[0]); + return Actions.ActOnInstanceMessage(ReceiverExpr, SI, LBracloc, RBracloc, + &KeyExprs[0]); } + SelectorInfo *SI = ObjcGetUnarySelectorInfo(selIdent, PP.getSelectorTable()); + // We've just parsed a unary message (a message with no arguments). if (ReceiverName) - return Actions.ActOnUnaryMessage(ReceiverName, selIdent, LBracloc,RBracloc); - return Actions.ActOnUnaryMessage(ReceiverExpr, selIdent, LBracloc,RBracloc); + return Actions.ActOnClassMessage(ReceiverName, SI, LBracloc, RBracloc, 0); + return Actions.ActOnInstanceMessage(ReceiverExpr, SI, LBracloc, RBracloc, 0); } Parser::ExprResult Parser::ParseObjCStringLiteral() { diff --git a/Sema/ASTStreamer.cpp b/Sema/ASTStreamer.cpp index 9dce95afb3..8e5adcad51 100644 --- a/Sema/ASTStreamer.cpp +++ b/Sema/ASTStreamer.cpp @@ -98,7 +98,7 @@ void clang::ParseAST(Preprocessor &PP, unsigned MainFileID, } ASTContext Context(PP.getSourceManager(), PP.getTargetInfo(), - PP.getIdentifierTable()); + PP.getIdentifierTable(), PP.getSelectorTable()); ASTStreamer Streamer(PP, Context, MainFileID); diff --git a/Sema/Sema.h b/Sema/Sema.h index bb83b0e6ae..a486d4fa73 100644 --- a/Sema/Sema.h +++ b/Sema/Sema.h @@ -391,32 +391,25 @@ public: DeclTy **Fields, unsigned NumFields); virtual DeclTy *ObjcBuildMethodDeclaration(SourceLocation MethodLoc, - tok::TokenKind MethodType, TypeTy *ReturnType, - ObjcKeywordDecl *Keywords, unsigned NumKeywords, - AttributeList *AttrList, - tok::ObjCKeywordKind MethodImplKind); - virtual DeclTy *ObjcBuildMethodDeclaration(SourceLocation MethodLoc, - tok::TokenKind MethodType, TypeTy *ReturnType, - IdentifierInfo *SelectorName, AttributeList *AttrList, - tok::ObjCKeywordKind MethodImplKind); + tok::TokenKind MethodType, TypeTy *ReturnType, SelectorInfo *Sel, + // optional arguments. The number of types/arguments is obtained + // from the Sel.getNumArgs(). + TypeTy **ArgTypes, IdentifierInfo **ArgNames, + AttributeList *AttrList, tok::ObjCKeywordKind MethodImplKind); - // This actions handles keyword message to classes. - virtual ExprResult ActOnKeywordMessage( - IdentifierInfo *receivingClassName, - ObjcKeywordMessage *Keywords, unsigned NumKeywords, - SourceLocation lbrac, SourceLocation rbrac); - // This action handles keyword messages to instances. - virtual ExprResult ActOnKeywordMessage(ExprTy *receiver, - ObjcKeywordMessage *Keywords, unsigned NumKeywords, - SourceLocation lbrac, SourceLocation rbrac); - // This actions handles unary message to classes. - virtual ExprResult ActOnUnaryMessage( - IdentifierInfo *receivingClassName, IdentifierInfo *selName, - SourceLocation lbrac, SourceLocation rbrac); - // This action handles unary messages to instances. - virtual ExprResult ActOnUnaryMessage( - ExprTy *receiver, IdentifierInfo *sName, - SourceLocation lbrac, SourceLocation rbrac); + // ActOnClassMessage - used for both unary and keyword messages. + // ArgExprs is optional - if it is present, the number of expressions + // is obtained from Sel.getNumArgs(). + virtual ExprResult ActOnClassMessage( + IdentifierInfo *receivingClassName, SelectorInfo *Sel, + SourceLocation lbrac, SourceLocation rbrac, ExprTy **ArgExprs); + + // ActOnInstanceMessage - used for both unary and keyword messages. + // ArgExprs is optional - if it is present, the number of expressions + // is obtained from Sel.getNumArgs(). + virtual ExprResult ActOnInstanceMessage( + ExprTy *receiver, SelectorInfo *Sel, + SourceLocation lbrac, SourceLocation rbrac, ExprTy **ArgExprs); private: // UsualUnaryConversions - promotes integers (C99 6.3.1.1p2) and converts // functions and arrays to their respective pointers (C99 6.3.2.1). diff --git a/Sema/SemaDecl.cpp b/Sema/SemaDecl.cpp index 1fb4142796..ae9c719471 100644 --- a/Sema/SemaDecl.cpp +++ b/Sema/SemaDecl.cpp @@ -1567,65 +1567,25 @@ void Sema::ObjcAddMethodsToClass(DeclTy *ClassDecl, } Sema::DeclTy *Sema::ObjcBuildMethodDeclaration(SourceLocation MethodLoc, - tok::TokenKind MethodType, TypeTy *ReturnType, - ObjcKeywordDecl *Keywords, unsigned NumKeywords, - AttributeList *AttrList, - tok::ObjCKeywordKind MethodDeclKind) { - assert(NumKeywords && "Selector must be specified"); - - // Derive the selector name from the keyword declarations. - int len=0; - for (unsigned int i = 0; i < NumKeywords; i++) { - if (Keywords[i].SelectorName) - len += strlen(Keywords[i].SelectorName->getName()); - len++; - } - llvm::SmallString<128> methodName; - methodName[0] = '\0'; - for (unsigned int i = 0; i < NumKeywords; i++) { - if (Keywords[i].SelectorName) - methodName += Keywords[i].SelectorName->getName(); - methodName += ":"; - } - methodName[len] = '\0'; - IdentifierInfo &SelName = Context.Idents.get(&methodName[0], - &methodName[0]+len); + tok::TokenKind MethodType, TypeTy *ReturnType, SelectorInfo *Sel, + // optional arguments. The number of types/arguments is obtained + // from the Sel.getNumArgs(). + TypeTy **ArgTypes, IdentifierInfo **ArgNames, + AttributeList *AttrList, tok::ObjCKeywordKind MethodDeclKind) { llvm::SmallVector<ParmVarDecl*, 16> Params; - for (unsigned i = 0; i < NumKeywords; i++) { - ObjcKeywordDecl *arg = &Keywords[i]; + for (unsigned i = 0; i < Sel->getNumArgs(); i++) { // FIXME: arg->AttrList must be stored too! - ParmVarDecl* Param = new ParmVarDecl(arg->ColonLoc, arg->ArgumentName, - QualType::getFromOpaquePtr(arg->TypeInfo), + ParmVarDecl* Param = new ParmVarDecl(SourceLocation(/*FIXME*/), ArgNames[i], + QualType::getFromOpaquePtr(ArgTypes[i]), VarDecl::None, 0); - // FIXME: 'InvalidType' does not get set by caller yet. - if (arg->InvalidType) - Param->setInvalidDecl(); Params.push_back(Param); } QualType resultDeclType = QualType::getFromOpaquePtr(ReturnType); - ObjcMethodDecl* ObjcMethod = new ObjcMethodDecl(MethodLoc, - SelName, resultDeclType, - 0, -1, AttrList, MethodType == tok::minus); - ObjcMethod->setMethodParams(&Params[0], NumKeywords); - if (MethodDeclKind == tok::objc_optional) - ObjcMethod->setDeclImplementation(ObjcMethodDecl::Optional); - else - ObjcMethod->setDeclImplementation(ObjcMethodDecl::Required); - return ObjcMethod; -} - -Sema::DeclTy *Sema::ObjcBuildMethodDeclaration(SourceLocation MethodLoc, - tok::TokenKind MethodType, TypeTy *ReturnType, - IdentifierInfo *SelectorName, AttributeList *AttrList, - tok::ObjCKeywordKind MethodDeclKind) { - const char *methodName = SelectorName->getName(); - IdentifierInfo &SelName = Context.Idents.get(methodName, - methodName+strlen(methodName)); - QualType resultDeclType = QualType::getFromOpaquePtr(ReturnType); - ObjcMethodDecl* ObjcMethod = new ObjcMethodDecl(MethodLoc, - SelName, resultDeclType, 0, -1, - AttrList, MethodType == tok::minus); + ObjcMethodDecl* ObjcMethod = new ObjcMethodDecl(MethodLoc, Sel, + resultDeclType, 0, -1, AttrList, + MethodType == tok::minus); + ObjcMethod->setMethodParams(&Params[0], Sel->getNumArgs()); if (MethodDeclKind == tok::objc_optional) ObjcMethod->setDeclImplementation(ObjcMethodDecl::Optional); else diff --git a/Sema/SemaExpr.cpp b/Sema/SemaExpr.cpp index 15bf4fd0cb..67aa04de99 100644 --- a/Sema/SemaExpr.cpp +++ b/Sema/SemaExpr.cpp @@ -1871,76 +1871,31 @@ Sema::ExprResult Sema::ParseObjCEncodeExpression(SourceLocation AtLoc, return new ObjCEncodeExpr(t, EncodedType, AtLoc, RParenLoc); } -static IdentifierInfo &DeriveSelector(ObjcKeywordMessage *Keywords, - unsigned NumKeywords, - ASTContext &Context) { - // Derive the selector name from the keyword declarations. - int len=0; - for (unsigned int i = 0; i < NumKeywords; i++) { - if (Keywords[i].SelectorName) - len += strlen(Keywords[i].SelectorName->getName()); - len++; - } - llvm::SmallString<128> methodName; - methodName[0] = '\0'; - for (unsigned int i = 0; i < NumKeywords; i++) { - if (Keywords[i].SelectorName) - methodName += Keywords[i].SelectorName->getName(); - methodName += ":"; - } - methodName[len] = '\0'; - return Context.Idents.get(&methodName[0], &methodName[0]+len); -} - -// This actions handles keyword message to classes. -Sema::ExprResult Sema::ActOnKeywordMessage( - IdentifierInfo *receivingClassName, - ObjcKeywordMessage *Keywords, unsigned NumKeywords, - SourceLocation lbrac, SourceLocation rbrac) +// ActOnClassMessage - used for both unary and keyword messages. +// ArgExprs is optional - if it is present, the number of expressions +// is obtained from Sel.getNumArgs(). +Sema::ExprResult Sema::ActOnClassMessage( + IdentifierInfo *receivingClassName, SelectorInfo *Sel, + SourceLocation lbrac, SourceLocation rbrac, ExprTy **Args) { - IdentifierInfo &SelName = DeriveSelector(Keywords, NumKeywords, Context); assert(receivingClassName && "missing receiver class name"); - return new ObjCMessageExpr(receivingClassName, SelName, Keywords, NumKeywords, - Context.IntTy/*FIXME*/, lbrac, rbrac); + Expr **ArgExprs = reinterpret_cast<Expr **>(Args); + return new ObjCMessageExpr(receivingClassName, Sel, + Context.IntTy/*FIXME*/, lbrac, rbrac, ArgExprs); } -// This action handles keyword messages to instances. -Sema::ExprResult Sema::ActOnKeywordMessage( - ExprTy *receiver, ObjcKeywordMessage *Keywords, unsigned NumKeywords, - SourceLocation lbrac, SourceLocation rbrac) { - IdentifierInfo &SelName = DeriveSelector(Keywords, NumKeywords, Context); - assert(receiver && "missing receiver expression"); - - Expr *RExpr = static_cast<Expr *>(receiver); - return new ObjCMessageExpr(RExpr, SelName, Keywords, NumKeywords, - Context.IntTy/*FIXME*/, lbrac, rbrac); -} - -// This actions handles unary message to classes. -Sema::ExprResult Sema::ActOnUnaryMessage( - IdentifierInfo *receivingClassName, IdentifierInfo *selName, - SourceLocation lbrac, SourceLocation rbrac) { - assert(receivingClassName && "missing receiver class name"); - - // FIXME: this should be passed in... - IdentifierInfo &SName = Context.Idents.get( - selName->getName(), selName->getName()+strlen(selName->getName())); - return new ObjCMessageExpr(receivingClassName, SName, - Context.IntTy/*FIXME*/, lbrac, rbrac); -} - -// This action handles unary messages to instances. -Sema::ExprResult Sema::ActOnUnaryMessage( - ExprTy *receiver, IdentifierInfo *selName, - SourceLocation lbrac, SourceLocation rbrac) { +// ActOnInstanceMessage - used for both unary and keyword messages. +// ArgExprs is optional - if it is present, the number of expressions +// is obtained from Sel.getNumArgs(). +Sema::ExprResult Sema::ActOnInstanceMessage( + ExprTy *receiver, SelectorInfo *Sel, + SourceLocation lbrac, SourceLocation rbrac, ExprTy **Args) +{ assert(receiver && "missing receiver expression"); Expr *RExpr = static_cast<Expr *>(receiver); - // FIXME: this should be passed in... - IdentifierInfo &SName = Context.Idents.get( - selName->getName(), selName->getName()+strlen(selName->getName())); - return new ObjCMessageExpr(RExpr, SName, - Context.IntTy/*FIXME*/, lbrac, rbrac); + Expr **ArgExprs = reinterpret_cast<Expr **>(Args); + return new ObjCMessageExpr(RExpr, Sel, + Context.IntTy/*FIXME*/, lbrac, rbrac, ArgExprs); } - diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index 91fa2abd97..f06f702dfd 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -14,17 +14,19 @@ #ifndef LLVM_CLANG_AST_ASTCONTEXT_H #define LLVM_CLANG_AST_ASTCONTEXT_H +#include "clang/Lex/IdentifierTable.h" // FIXME: Move IdentifierTable to Basic #include "clang/AST/Builtins.h" #include "clang/AST/Expr.h" #include "clang/AST/RecordLayout.h" #include "clang/AST/Type.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/StringMap.h" +#include "llvm/ADT/FoldingSet.h" #include <vector> namespace clang { class TargetInfo; - + /// ASTContext - This class holds long-lived AST nodes (such as types and /// decls) that can be referred to throughout the semantic analysis of a file. class ASTContext { @@ -46,6 +48,7 @@ public: SourceManager &SourceMgr; TargetInfo &Target; IdentifierTable &Idents; + llvm::FoldingSet<SelectorInfo> &Selectors; Builtin::Context BuiltinInfo; // Builtin Types. @@ -58,8 +61,10 @@ public: QualType FloatTy, DoubleTy, LongDoubleTy; QualType FloatComplexTy, DoubleComplexTy, LongDoubleComplexTy; - ASTContext(SourceManager &SM, TargetInfo &t, IdentifierTable &idents) : - CFConstantStringTypeDecl(0), SourceMgr(SM), Target(t), Idents(idents) { + ASTContext(SourceManager &SM, TargetInfo &t, IdentifierTable &idents, + llvm::FoldingSet<SelectorInfo> &sels) : + CFConstantStringTypeDecl(0), SourceMgr(SM), Target(t), + Idents(idents), Selectors(sels) { InitBuiltinTypes(); BuiltinInfo.InitializeBuiltins(idents, Target); } diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index b420c1da81..ea8121326e 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -20,6 +20,7 @@ namespace clang { class IdentifierInfo; +class SelectorInfo; class Expr; class Stmt; class FunctionDecl; @@ -665,7 +666,7 @@ public: enum ImplementationControl { None, Required, Optional }; private: // A unigue name for this method. - IdentifierInfo &Selector; + SelectorInfo *Selector; // Type of this method. QualType MethodDeclType; @@ -683,14 +684,14 @@ private: ImplementationControl DeclImplementation : 2; public: - ObjcMethodDecl(SourceLocation L, IdentifierInfo &SelId, QualType T, + ObjcMethodDecl(SourceLocation L, SelectorInfo *SelInfo, QualType T, ParmVarDecl **paramInfo = 0, int numParams=-1, AttributeList *M = 0, bool isInstance = true, Decl *PrevDecl = 0) - : Decl(ObjcMethod), Selector(SelId), MethodDeclType(T), + : Decl(ObjcMethod), Selector(SelInfo), MethodDeclType(T), ParamInfo(paramInfo), NumMethodParams(numParams), MethodAttrs(M), IsInstance(isInstance) {} - +#if 0 ObjcMethodDecl(Kind DK, SourceLocation L, IdentifierInfo &SelId, QualType T, ParmVarDecl **paramInfo = 0, int numParams=-1, AttributeList *M = 0, bool isInstance = true, @@ -698,7 +699,7 @@ public: : Decl(DK), Selector(SelId), MethodDeclType(T), ParamInfo(paramInfo), NumMethodParams(numParams), MethodAttrs(M), IsInstance(isInstance) {} - +#endif virtual ~ObjcMethodDecl(); QualType getMethodType() const { return MethodDeclType; } unsigned getNumMethodParams() const { return NumMethodParams; } diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h index 73f730ef64..046c73a44c 100644 --- a/include/clang/AST/Expr.h +++ b/include/clang/AST/Expr.h @@ -22,9 +22,9 @@ namespace clang { class IdentifierInfo; + class SelectorInfo; class Decl; class ASTContext; - struct ObjcKeywordMessage; /// Expr - This represents one expression. Note that Expr's are subclasses of /// Stmt. This allows an expression to be transparently used any place a Stmt @@ -1073,36 +1073,25 @@ public: class ObjCMessageExpr : public Expr { enum { RECEIVER=0, ARGS_START=1 }; - - // The following 3 slots are only used for keyword messages. - // Adding a subclass could save us some space. For now, we keep it simple. + Expr **SubExprs; - unsigned NumArgs; // A unigue name for this message. - IdentifierInfo &Selector; - - IdentifierInfo **KeyIdents; + SelectorInfo *Selector; - IdentifierInfo *ClassName; + IdentifierInfo *ClassName; // optional - 0 for instance messages. SourceLocation LBracloc, RBracloc; public: - // constructor for unary messages. + // constructor for class messages. // FIXME: clsName should be typed to ObjCInterfaceType - ObjCMessageExpr(IdentifierInfo *clsName, IdentifierInfo &selInfo, - QualType retType, SourceLocation LBrac, SourceLocation RBrac); - ObjCMessageExpr(Expr *receiver, IdentifierInfo &selInfo, - QualType retType, SourceLocation LBrac, SourceLocation RBrac); - - // constructor for keyword messages. - // FIXME: clsName should be typed to ObjCInterfaceType - ObjCMessageExpr(IdentifierInfo *clsName, IdentifierInfo &selInfo, - ObjcKeywordMessage *keys, unsigned numargs, QualType retType, - SourceLocation LBrac, SourceLocation RBrac); - ObjCMessageExpr(Expr *receiver, IdentifierInfo &selInfo, - ObjcKeywordMessage *keys, unsigned numargs, QualType retType, - SourceLocation LBrac, SourceLocation RBrac); + ObjCMessageExpr(IdentifierInfo *clsName, SelectorInfo *selInfo, + QualType retType, SourceLocation LBrac, SourceLocation RBrac, + Expr **ArgExprs); + // constructor for instance messages. + ObjCMessageExpr(Expr *receiver, SelectorInfo *selInfo, + QualType retType, SourceLocation LBrac, SourceLocation RBrac, + Expr **ArgExprs); ~ObjCMessageExpr() { delete [] SubExprs; } @@ -1112,17 +1101,12 @@ public: /// getNumArgs - Return the number of actual arguments to this call. /// - unsigned getNumArgs() const { return NumArgs; } + unsigned getNumArgs() const; /// getArg - Return the specified argument. - Expr *getArg(unsigned Arg) { - assert(Arg < NumArgs && "Arg access out of range!"); - return SubExprs[Arg+ARGS_START]; - } - const Expr *getArg(unsigned Arg) const { - assert(Arg < NumArgs && "Arg access out of range!"); - return SubExprs[Arg+ARGS_START]; - } + Expr *getArg(unsigned Arg); + const Expr *getArg(unsigned Arg) const; + SourceRange getSourceRange() const { return SourceRange(LBracloc, RBracloc); } static bool classof(const Stmt *T) { diff --git a/include/clang/Lex/IdentifierTable.h b/include/clang/Lex/IdentifierTable.h index fd2cb6ae71..9b08202988 100644 --- a/include/clang/Lex/IdentifierTable.h +++ b/include/clang/Lex/IdentifierTable.h @@ -14,8 +14,12 @@ #ifndef LLVM_CLANG_LEX_IDENTIFIERTABLE_H #define LLVM_CLANG_LEX_IDENTIFIERTABLE_H +// FIXME: Move this header header/module to the "Basic" library. Unlike Lex, +// this data is long-lived. #include "clang/Basic/TokenKinds.h" #include "llvm/ADT/StringMap.h" +#include "llvm/ADT/FoldingSet.h" +#include "llvm/ADT/SmallString.h" #include <string> #include <cassert> @@ -166,6 +170,65 @@ private: void AddKeywords(const LangOptions &LangOpts); }; +/// SelectorInfo - One of these variable length records is kept for each parsed +/// selector (similar in spirit to IdentifierInfo). We use a folding set to +/// unique aggregate names (keyword selectors in ObjC parlance). +class SelectorInfo : public llvm::FoldingSetNode { + unsigned NumArgs; + void *ActionInfo; // Managed by the ObjC actions module. +public: + // Constructor for keyword selectors. + SelectorInfo(unsigned nKeys, IdentifierInfo **IIV) { + assert(nKeys && "SelectorInfo(): not a keyword selector"); + NumArgs = nKeys; + // Fill in the trailing keyword array. + IdentifierInfo **KeyInfo = reinterpret_cast<IdentifierInfo **>(this+1); + for (unsigned i = 0; i != nKeys; ++i) + KeyInfo[i] = IIV[i]; + } + // Constructor for unary selectors (no colons/arguments). + SelectorInfo(IdentifierInfo *unarySelector) { + NumArgs = 0; + IdentifierInfo **UnaryInfo = reinterpret_cast<IdentifierInfo **>(this+1); + UnaryInfo[0] = unarySelector; + } + // Derive the full selector n |