Add SelectorInfo (similar in spirit to IdentifierInfo). The key difference is SelectorInfo is not string-oriented, it is a unique aggregate of IdentifierInfo's (using a folding set). SelectorInfo also has a richer API that simplifies the parser/action interface. 3 noteworthy benefits:
#1: It is cleaner. I never "liked" storing keyword selectors (i.e. foo:bar:baz) in the IdentifierTable.
#2: It is more space efficient. Since Cocoa keyword selectors can be quite long, this technique is space saving. For Cocoa.h, pulling the keyword selectors out saves ~180k. The cost of the SelectorInfo data is ~100k. Saves ~80k, or 43%.
#3: It results in many API simplifications. Here are some highlights:
- Removed 3 actions (ActOnKeywordMessage, ActOnUnaryMessage, & one flavor of ObjcBuildMethodDeclaration that was specific to unary messages).
- Removed 3 funky structs from DeclSpec.h (ObjcKeywordMessage, ObjcKeywordDecl, and ObjcKeywordInfo).
- Removed 2 ivars and 2 constructors from ObjCMessageExpr (fyi, this space savings has not been measured).
I am happy with the way it turned out (though it took a bit more hacking than I expected). Given the central role of selectors in ObjC, making sure this is "right" will pay dividends later.
Thanks to Chris for talking this through with me and suggesting this approach.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@42395 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/Sema/ASTStreamer.cpp b/Sema/ASTStreamer.cpp
index 9dce95a..8e5adca 100644
--- a/Sema/ASTStreamer.cpp
+++ b/Sema/ASTStreamer.cpp
@@ -98,7 +98,7 @@
}
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 bb83b0e..a486d4f 100644
--- a/Sema/Sema.h
+++ b/Sema/Sema.h
@@ -391,32 +391,25 @@
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 1fb4142..ae9c719 100644
--- a/Sema/SemaDecl.cpp
+++ b/Sema/SemaDecl.cpp
@@ -1567,65 +1567,25 @@
}
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 15bf4fd..67aa04d 100644
--- a/Sema/SemaExpr.cpp
+++ b/Sema/SemaExpr.cpp
@@ -1871,76 +1871,31 @@
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);
+// 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);
- return new ObjCMessageExpr(RExpr, SelName, Keywords, NumKeywords,
- Context.IntTy/*FIXME*/, lbrac, rbrac);
+ Expr **ArgExprs = reinterpret_cast<Expr **>(Args);
+ return new ObjCMessageExpr(RExpr, Sel,
+ Context.IntTy/*FIXME*/, lbrac, rbrac, ArgExprs);
}
-
-// 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) {
- 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);
-}
-