aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--AST/Expr.cpp74
-rw-r--r--Lex/IdentifierTable.cpp23
-rw-r--r--Parse/ParseObjc.cpp130
-rw-r--r--Sema/ASTStreamer.cpp2
-rw-r--r--Sema/Sema.h43
-rw-r--r--Sema/SemaDecl.cpp64
-rw-r--r--Sema/SemaExpr.cpp83
-rw-r--r--include/clang/AST/ASTContext.h11
-rw-r--r--include/clang/AST/Decl.h11
-rw-r--r--include/clang/AST/Expr.h48
-rw-r--r--include/clang/Lex/IdentifierTable.h63
-rw-r--r--include/clang/Lex/Preprocessor.h13
-rw-r--r--include/clang/Parse/Action.h61
-rw-r--r--include/clang/Parse/DeclSpec.h20
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