]> granicus.if.org Git - clang/commitdiff
Add SelectorInfo (similar in spirit to IdentifierInfo). The key difference is Selecto...
authorSteve Naroff <snaroff@apple.com>
Thu, 27 Sep 2007 14:38:14 +0000 (14:38 +0000)
committerSteve Naroff <snaroff@apple.com>
Thu, 27 Sep 2007 14:38:14 +0000 (14:38 +0000)
#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

14 files changed:
AST/Expr.cpp
Lex/IdentifierTable.cpp
Parse/ParseObjc.cpp
Sema/ASTStreamer.cpp
Sema/Sema.h
Sema/SemaDecl.cpp
Sema/SemaExpr.cpp
include/clang/AST/ASTContext.h
include/clang/AST/Decl.h
include/clang/AST/Expr.h
include/clang/Lex/IdentifierTable.h
include/clang/Lex/Preprocessor.h
include/clang/Parse/Action.h
include/clang/Parse/DeclSpec.h

index 0b1c7994fffbde3b74f28e07417d26f010332eb5..312d209e2dbfc4abe8bf9408ddb5b9057903e75f 100644 (file)
@@ -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]);
 }
 
index d3faeb58dba50fe40a0d6689e25e38b061508d17..6ab0ef1a69b1ed4e56eb480d3dd0c074591c2a8a 100644 (file)
@@ -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();
 }
+
index eddbb4a2541893ed8b1e37bf78adeb0eecd0e356..16434cdcddbfc909d3dcc025377239f2134e08b8 100644 (file)
@@ -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() {
index 9dce95afb3243b8869f3258e0ca5b119ef4a1bd4..8e5adcad5132de6c06d5e1240e0931c0656fab52 100644 (file)
@@ -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);
   
index bb83b0e6aeda91a57f7369d4b4d74a346d0346e7..a486d4fa73a25e7ed51280c84865e9114e49b935 100644 (file)
@@ -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). 
index 1fb4142796014eaf262af5c0e6c7d7d1c8da4a59..ae9c719471b451786c2730d5a7001decf88a7351 100644 (file)
@@ -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
index 15bf4fd0cb630e67e6e0659069b426dac7edb52d..67aa04de99f3a475d14096ed46f74598c2947ed9 100644 (file)
@@ -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);
 }
-
index 91fa2abd97d0e2d6c9887a10d5809fe585f0b716..f06f702dfd4dbbaed529f0007ee9cd42d575a170 100644 (file)
 #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);
   }    
index b420c1da813f871c4b40d354ef7225f7ef6469f0..ea8121326e1fcdee5df25eb0c3c3159000ac5608 100644 (file)
@@ -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; }
index 73f730ef6406329476998a976616522e4214fa6f..046c73a44c963e289261ece03ba78e5800b2aba6 100644 (file)
@@ -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) {
index fd2cb6ae717807f8d0938198004c3bdb05caf0b8..9b08202988bd34cc0f1e0d75dd104f5aa4edfcc5 100644 (file)
 #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 name, placing the result into methodBuffer.
+  // As a convenience, a pointer to the first character is returned.
+  char *getName(llvm::SmallString<128> methodBuffer);
+
+  unsigned getNumArgs() const { return NumArgs; }
+  
+  // Predicates to identify the selector type.
+  bool isKeywordSelector() const { return NumArgs > 0; }
+  bool isUnarySelector() const { return NumArgs == 0; }
+  
+  /// getActionInfo/setActionInfo - The actions module is allowed to
+  /// associate arbitrary metadata with this selector.
+  template<typename T>
+  T *getActionInfo() const { return static_cast<T*>(ActionInfo); }
+  void setActionInfo(void *T) { ActionInfo = T; }
+  
+  typedef const IdentifierInfo *const *keyword_iterator;
+  keyword_iterator keyword_begin() const {
+    return reinterpret_cast<keyword_iterator>(this+1);
+  }
+  keyword_iterator keyword_end() const { 
+    return keyword_begin()+NumArgs; 
+  }
+  static void Profile(llvm::FoldingSetNodeID &ID, 
+                      keyword_iterator ArgTys, unsigned NumArgs) {
+    ID.AddInteger(NumArgs);
+    if (NumArgs) { // handle keyword selector.
+      for (unsigned i = 0; i != NumArgs; ++i)
+        ID.AddPointer(ArgTys[i]);
+    } else // handle unary selector.
+      ID.AddPointer(ArgTys[0]);
+  }
+  void Profile(llvm::FoldingSetNodeID &ID) {
+    Profile(ID, keyword_begin(), NumArgs);
+  }
+};
+
 }  // end namespace clang
 
 #endif
index ff1faaa58c60e2b206966985f7d78722d1d305da..b3008375d800fc796991d98ce640c5984c11ddcf 100644 (file)
@@ -18,6 +18,7 @@
 #include "clang/Lex/Lexer.h"
 #include "clang/Lex/MacroExpander.h"
 #include "clang/Basic/SourceLocation.h"
+#include "llvm/ADT/FoldingSet.h"
 
 namespace clang {
   
@@ -73,6 +74,15 @@ class Preprocessor {
   /// the program, including program keywords.
   IdentifierTable Identifiers;
   
+  /// Selectors - This table contains all the selectors in the program. Unlike
+  /// IdentifierTable above, this table *isn't* populated by the preprocessor.
+  /// It is declared/instantiated here because it's role/lifetime is 
+  /// conceptually similar the IdentifierTable. In addition, the current control
+  /// flow (in clang::ParseAST()), make it convenient to put here. 
+  /// FIXME: Make sure the lifetime of Identifiers/Selectors *isn't* tied to
+  /// the lifetime fo the preprocessor.
+  llvm::FoldingSet<SelectorInfo> Selectors;
+  
   /// PragmaHandlers - This tracks all of the pragmas that the client registered
   /// with this preprocessor.
   PragmaNamespace *PragmaHandlers;
@@ -132,7 +142,8 @@ public:
   HeaderSearch &getHeaderSearchInfo() const { return HeaderInfo; }
 
   IdentifierTable &getIdentifierTable() { return Identifiers; }
-
+  llvm::FoldingSet<SelectorInfo> &getSelectorTable() { return Selectors; }
+  
   /// SetCommentRetentionState - Control whether or not the preprocessor retains
   /// comments in output.
   void SetCommentRetentionState(bool KeepComments, bool KeepMacroComments) {
index bc14226bec0f4b519809be5e13e533494d34a160..3e9a687ef4fd97467c456b9d569cd86cb3d99fe7 100644 (file)
@@ -21,14 +21,13 @@ namespace clang {
   // Semantic.
   class DeclSpec;
   class Declarator;
-  struct ObjcKeywordDecl;
-  struct ObjcKeywordMessage;
   class AttributeList;
   // Parse.
   class Scope;
   class Action;
+  class SelectorInfo;
   // Lex.
-  class IdentifierInfo;
+  class IdentifierInfo; // FIXME: should be in Basic, not Lex.
   class Token;
 
 /// Action - As the parser reads the input file and recognizes the productions
@@ -472,41 +471,27 @@ public:
     return 0;
   }
   virtual DeclTy *ObjcBuildMethodDeclaration(SourceLocation MethodLoc, 
-    tok::TokenKind MethodType, TypeTy *ReturnType,
-    ObjcKeywordDecl *Keywords, unsigned NumKeywords, 
-    AttributeList *AttrList,
-    tok::ObjCKeywordKind MethodImplKind) {
-    return 0;
-  }
-  virtual DeclTy *ObjcBuildMethodDeclaration(SourceLocation MethodLoc, 
-    tok::TokenKind MethodType, TypeTy *ReturnType,
-    IdentifierInfo *SelectorName, AttributeList *AttrList,
-    tok::ObjCKeywordKind MethodImplKind) {
-    return 0;
-  }
-  // This actions handles keyword message to classes.
-  virtual ExprResult ActOnKeywordMessage(
-    IdentifierInfo *receivingClassName, 
-    ObjcKeywordMessage *Keywords, unsigned NumKeywords,
-    SourceLocation lbrac, SourceLocation rbrac) {
-    return 0;
-  }
-  // This action handles keyword messages to instances.
-  virtual ExprResult ActOnKeywordMessage(ExprTy *receiver, 
-    ObjcKeywordMessage *Keywords, unsigned NumKeywords,
-    SourceLocation lbrac, SourceLocation rbrac) {
-    return 0;
-  }
-  // This actions handles unary message to classes.
-  virtual ExprResult ActOnUnaryMessage(
-    IdentifierInfo *receivingClassName, IdentifierInfo *selName,
-    SourceLocation lbrac, SourceLocation rbrac) {
-    return 0;
-  }
-  // This action handles unary messages to instances.
-  virtual ExprResult ActOnUnaryMessage(
-    ExprTy *receiver, IdentifierInfo *sName,
-    SourceLocation lbrac, SourceLocation rbrac) {
+    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) {
+    return 0;
+  }
+  // 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) {
+    return 0;
+  }
+  // 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) {
     return 0;
   }
   virtual DeclTy *ObjcClassDeclaration(Scope *S, SourceLocation AtClassLoc,
index 73254cd6824178d4d12464fd4386dce78c1ee424..c17469dd255d10908cdba6d07f41afd0ce54bc24 100644 (file)
@@ -562,26 +562,6 @@ public:
   bool getInvalidType() { return InvalidType; }
 };
 
-/// ObjCKeyword* - The following 3 small value structures capture keyword
-/// information passed from the parser to the actions. Like Declarator above,
-/// instances of these structures are transient objects that live on the stack.
-struct ObjcKeywordInfo {
-  IdentifierInfo *SelectorName; // optional
-  SourceLocation SelectorLoc;
-  SourceLocation ColonLoc;
-};
-
-struct ObjcKeywordDecl : ObjcKeywordInfo {
-  Action::TypeTy *TypeInfo; // optional
-  IdentifierInfo *ArgumentName;
-  AttributeList *AttrList;
-  bool InvalidType;  // FIXME: is this used?
-};
-  
-struct ObjcKeywordMessage : ObjcKeywordInfo {
-  Action::ExprTy *KeywordExpr;
-};
-
 } // end namespace clang
 
 #endif