Progress on message expressions...

- Add ObjcMessageExpr AST node and associated constructors.
- Add SourceLocation's to ActOnKeywordMessage/ActOnUnaryMessage API.
- Instantiate message expressions...
- Replace alloca usage with SmallString.

Next step, installing a correct type, among other tweaks...

llvm-svn: 42116
This commit is contained in:
Steve Naroff 2007-09-18 23:55:05 +00:00
parent fb9ea52a13
commit d54978ba8b
10 changed files with 244 additions and 49 deletions

View File

@ -15,6 +15,8 @@
#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;
//===----------------------------------------------------------------------===//
@ -854,6 +856,52 @@ unsigned OCUVectorElementExpr::getEncodedElementAccess() const {
return Result;
}
// constructor for unary messages.
ObjCMessageExpr::ObjCMessageExpr(
IdentifierInfo *clsName, SelectorInfo &methName, QualType retType,
SourceLocation LBrac, SourceLocation RBrac)
: Expr(ObjCMessageExprClass, retType), Selector(methName) {
ClassName = clsName;
LBracloc = LBrac;
RBracloc = RBrac;
}
ObjCMessageExpr::ObjCMessageExpr(
Expr *fn, SelectorInfo &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, SelectorInfo &selInfo, ObjcKeywordMessage *keys, unsigned numargs,
QualType retType, SourceLocation LBrac, SourceLocation RBrac)
: 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);
LBracloc = LBrac;
RBracloc = RBrac;
}
ObjCMessageExpr::ObjCMessageExpr(
IdentifierInfo *clsName, SelectorInfo &selInfo, ObjcKeywordMessage *keys,
unsigned numargs, QualType retType, SourceLocation LBrac, SourceLocation RBrac)
: Expr(ObjCMessageExprClass, retType), Selector(selInfo), ClassName(clsName) {
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);
LBracloc = LBrac;
RBracloc = RBrac;
}
//===----------------------------------------------------------------------===//
// Child Iterators for iterating over subexpressions/substatements
//===----------------------------------------------------------------------===//
@ -1023,3 +1071,11 @@ Stmt::child_iterator ObjCStringLiteral::child_end() { return NULL; }
Stmt::child_iterator ObjCEncodeExpr::child_begin() { return NULL; }
Stmt::child_iterator ObjCEncodeExpr::child_end() { return NULL; }
// ObjCMessageExpr
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]);
}

View File

@ -612,6 +612,17 @@ void StmtPrinter::VisitObjCEncodeExpr(ObjCEncodeExpr *Node) {
OS << Node->getEncodedType().getAsString() << ")";
}
void StmtPrinter::VisitObjCMessageExpr(ObjCMessageExpr *Mess) {
OS << "[";
PrintExpr(Mess->getReceiver());
for (unsigned i = 0, e = Mess->getNumArgs(); i != e; ++i) {
// FIXME: get/print keyword...
PrintExpr(Mess->getArg(i));
}
OS << "]";
}
//===----------------------------------------------------------------------===//
// Stmt method implementations
//===----------------------------------------------------------------------===//

View File

@ -1007,7 +1007,7 @@ Parser::ExprResult Parser::ParseObjCExpression() {
///
Parser::ExprResult Parser::ParseObjCMessageExpression() {
assert(Tok.getKind() == tok::l_square && "'[' expected");
SourceLocation Loc = ConsumeBracket(); // consume '['
SourceLocation LBracloc = ConsumeBracket(); // consume '['
IdentifierInfo *ReceiverName = 0;
ExprTy *ReceiverExpr = 0;
// Parse receiver
@ -1073,20 +1073,22 @@ Parser::ExprResult Parser::ParseObjCMessageExpression() {
SkipUntil(tok::semi);
return 0;
}
ConsumeBracket(); // consume ']'
SourceLocation RBracloc = ConsumeBracket(); // consume ']'
if (KeyInfo.size()) {
// We've just parsed a keyword message.
if (ReceiverName)
return Actions.ActOnKeywordMessage(ReceiverName,
&KeyInfo[0], KeyInfo.size());
&KeyInfo[0], KeyInfo.size(),
LBracloc, RBracloc);
return Actions.ActOnKeywordMessage(ReceiverExpr,
&KeyInfo[0], KeyInfo.size());
&KeyInfo[0], KeyInfo.size(),
LBracloc, RBracloc);
}
// We've just parsed a unary message (a message with no arguments).
if (ReceiverName)
return Actions.ActOnUnaryMessage(ReceiverName, selIdent);
return Actions.ActOnUnaryMessage(ReceiverExpr, selIdent);
return Actions.ActOnUnaryMessage(ReceiverName, selIdent, LBracloc,RBracloc);
return Actions.ActOnUnaryMessage(ReceiverExpr, selIdent, LBracloc,RBracloc);
}
Parser::ExprResult Parser::ParseObjCStringLiteral() {

View File

@ -384,17 +384,22 @@ public:
tok::ObjCKeywordKind MethodImplKind);
// This actions handles keyword message to classes.
virtual ExprResult ActOnKeywordMessage(IdentifierInfo *receivingClassName,
ObjcKeywordMessage *Keywords, unsigned NumKeywords);
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);
// This actions handles keyword message to classes.
virtual ExprResult ActOnUnaryMessage(IdentifierInfo *receivingClassName,
IdentifierInfo *selName);
// This action handles keyword messages to instances.
virtual ExprResult ActOnUnaryMessage(ExprTy *receiver, IdentifierInfo *sName);
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);
private:
// UsualUnaryConversions - promotes integers (C99 6.3.1.1p2) and converts
// functions and arrays to their respective pointers (C99 6.3.2.1).

View File

@ -23,6 +23,7 @@
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/TargetInfo.h"
#include "llvm/Config/config.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallSet.h"
#if !defined(LLVM_ON_WIN32)
#include <alloca.h>
@ -1298,21 +1299,21 @@ Sema::DeclTy *Sema::ObjcBuildMethodDeclaration(SourceLocation MethodLoc,
// Derive the selector name from the keyword declarations.
int len=0;
char *methodName;
for (unsigned int i = 0; i < NumKeywords; i++) {
if (Keywords[i].SelectorName)
len += strlen(Keywords[i].SelectorName->getName());
len++;
}
methodName = (char *) alloca (len + 1);
llvm::SmallString<128> methodName;
methodName[0] = '\0';
for (unsigned int i = 0; i < NumKeywords; i++) {
if (Keywords[i].SelectorName)
strcat(methodName, Keywords[i].SelectorName->getName());
strcat(methodName, ":");
methodName += Keywords[i].SelectorName->getName();
methodName += ":";
}
SelectorInfo &SelName = Context.getSelectorInfo(methodName, methodName+len);
methodName[len] = '\0';
SelectorInfo &SelName = Context.getSelectorInfo(&methodName[0],
&methodName[0]+len);
llvm::SmallVector<ParmVarDecl*, 16> Params;
for (unsigned i = 0; i < NumKeywords; i++) {
@ -1332,9 +1333,9 @@ Sema::DeclTy *Sema::ObjcBuildMethodDeclaration(SourceLocation MethodLoc,
0, -1, AttrList, MethodType == tok::minus);
ObjcMethod->setMethodParams(&Params[0], NumKeywords);
if (MethodDeclKind == tok::objc_optional)
ObjcMethod->setDeclImplementation(ObjcMethodDecl::Optional);
ObjcMethod->setDeclImplementation(ObjcMethodDecl::Optional);
else
ObjcMethod->setDeclImplementation(ObjcMethodDecl::Required);
ObjcMethod->setDeclImplementation(ObjcMethodDecl::Required);
return ObjcMethod;
}
@ -1350,9 +1351,9 @@ Sema::DeclTy *Sema::ObjcBuildMethodDeclaration(SourceLocation MethodLoc,
SelName, resultDeclType, 0, -1,
AttrList, MethodType == tok::minus);
if (MethodDeclKind == tok::objc_optional)
ObjcMethod->setDeclImplementation(ObjcMethodDecl::Optional);
ObjcMethod->setDeclImplementation(ObjcMethodDecl::Optional);
else
ObjcMethod->setDeclImplementation(ObjcMethodDecl::Required);
ObjcMethod->setDeclImplementation(ObjcMethodDecl::Required);
return ObjcMethod;
}

View File

@ -15,6 +15,7 @@
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/AST/Expr.h"
#include "clang/Parse/DeclSpec.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Lex/LiteralSupport.h"
#include "clang/Basic/SourceManager.h"
@ -1856,28 +1857,76 @@ Sema::ExprResult Sema::ParseObjCEncodeExpression(SourceLocation AtLoc,
return new ObjCEncodeExpr(t, EncodedType, AtLoc, RParenLoc);
}
static SelectorInfo &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.getSelectorInfo(&methodName[0], &methodName[0]+len);
}
// This actions handles keyword message to classes.
Sema::ExprResult Sema::ActOnKeywordMessage(IdentifierInfo *receivingClassName,
ObjcKeywordMessage *Keywords, unsigned NumKeywords)
Sema::ExprResult Sema::ActOnKeywordMessage(
IdentifierInfo *receivingClassName,
ObjcKeywordMessage *Keywords, unsigned NumKeywords,
SourceLocation lbrac, SourceLocation rbrac)
{
return 0;
SelectorInfo &SelName = DeriveSelector(Keywords, NumKeywords, Context);
assert(receivingClassName && "missing receiver class name");
return new ObjCMessageExpr(receivingClassName, SelName, Keywords, NumKeywords,
Context.IntTy/*FIXME*/, lbrac, rbrac);
}
// This action handles keyword messages to instances.
Sema::ExprResult Sema::ActOnKeywordMessage(ExprTy *receiver,
ObjcKeywordMessage *Keywords, unsigned NumKeywords) {
return 0;
Sema::ExprResult Sema::ActOnKeywordMessage(
ExprTy *receiver, ObjcKeywordMessage *Keywords, unsigned NumKeywords,
SourceLocation lbrac, SourceLocation rbrac) {
SelectorInfo &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 keyword message to classes.
Sema::ExprResult Sema::ActOnUnaryMessage(IdentifierInfo *receivingClassName,
IdentifierInfo *selName) {
return 0;
// 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...
SelectorInfo &SName = Context.getSelectorInfo(
selName->getName(), selName->getName()+strlen(selName->getName()));
return new ObjCMessageExpr(receivingClassName, SName,
Context.IntTy/*FIXME*/, lbrac, rbrac);
}
// This action handles keyword messages to instances.
Sema::ExprResult Sema::ActOnUnaryMessage(ExprTy *receiver,
IdentifierInfo *selName) {
return 0;
// 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...
SelectorInfo &SName = Context.getSelectorInfo(
selName->getName(), selName->getName()+strlen(selName->getName()));
return new ObjCMessageExpr(RExpr, SName,
Context.IntTy/*FIXME*/, lbrac, rbrac);
}

View File

@ -708,7 +708,6 @@
08FB7793FE84155DC02AAC07 /* Project object */ = {
isa = PBXProject;
buildConfigurationList = 1DEB923508733DC60010E9CD /* Build configuration list for PBXProject "clang" */;
compatibilityVersion = "Xcode 2.4";
hasScannedForEncodings = 1;
mainGroup = 08FB7794FE84155DC02AAC07 /* clang */;
projectDirPath = "";

View File

@ -23,6 +23,7 @@ namespace clang {
class IdentifierInfo;
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
@ -1058,6 +1059,70 @@ public:
virtual child_iterator child_end();
};
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.
SelectorInfo &Selector;
IdentifierInfo **KeyIdents;
IdentifierInfo *ClassName;
SourceLocation LBracloc, RBracloc;
public:
// constructor for unary messages.
// FIXME: clsName should be typed to ObjCInterfaceType
ObjCMessageExpr(IdentifierInfo *clsName, SelectorInfo &selInfo,
QualType retType, SourceLocation LBrac, SourceLocation RBrac);
ObjCMessageExpr(Expr *receiver, SelectorInfo &selInfo,
QualType retType, SourceLocation LBrac, SourceLocation RBrac);
// constructor for keyword messages.
// FIXME: clsName should be typed to ObjCInterfaceType
ObjCMessageExpr(IdentifierInfo *clsName, SelectorInfo &selInfo,
ObjcKeywordMessage *keys, unsigned numargs, QualType retType,
SourceLocation LBrac, SourceLocation RBrac);
ObjCMessageExpr(Expr *receiver, SelectorInfo &selInfo,
ObjcKeywordMessage *keys, unsigned numargs, QualType retType,
SourceLocation LBrac, SourceLocation RBrac);
~ObjCMessageExpr() {
delete [] SubExprs;
}
const Expr *getReceiver() const { return SubExprs[RECEIVER]; }
Expr *getReceiver() { return SubExprs[RECEIVER]; }
/// getNumArgs - Return the number of actual arguments to this call.
///
unsigned getNumArgs() const { return NumArgs; }
/// 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];
}
SourceRange getSourceRange() const { return SourceRange(LBracloc, RBracloc); }
static bool classof(const Stmt *T) {
return T->getStmtClass() == ObjCMessageExprClass;
}
static bool classof(const ObjCMessageExpr *) { return true; }
// Iterators
virtual child_iterator child_begin();
virtual child_iterator child_end();
};
} // end namespace clang
#endif

View File

@ -80,8 +80,9 @@ STMT(61, CXXBoolLiteralExpr , Expr)
// Obj-C Expressions.
STMT(70, ObjCStringLiteral , Expr)
STMT(71, ObjCEncodeExpr , Expr)
STMT(72, ObjCMessageExpr , Expr)
LAST_EXPR(71)
LAST_EXPR(72)
#undef STMT
#undef FIRST_STMT

View File

@ -473,22 +473,28 @@ public:
return 0;
}
// This actions handles keyword message to classes.
virtual ExprResult ActOnKeywordMessage(IdentifierInfo *receivingClassName,
ObjcKeywordMessage *Keywords, unsigned NumKeywords) {
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) {
ObjcKeywordMessage *Keywords, unsigned NumKeywords,
SourceLocation lbrac, SourceLocation rbrac) {
return 0;
}
// This actions handles keyword message to classes.
virtual ExprResult ActOnUnaryMessage(IdentifierInfo *receivingClassName,
IdentifierInfo *selName) {
// This actions handles unary message to classes.
virtual ExprResult ActOnUnaryMessage(
IdentifierInfo *receivingClassName, IdentifierInfo *selName,
SourceLocation lbrac, SourceLocation rbrac) {
return 0;
}
// This action handles keyword messages to instances.
virtual ExprResult ActOnUnaryMessage(ExprTy *receiver,IdentifierInfo *sName) {
// This action handles unary messages to instances.
virtual ExprResult ActOnUnaryMessage(
ExprTy *receiver, IdentifierInfo *sName,
SourceLocation lbrac, SourceLocation rbrac) {
return 0;
}
virtual DeclTy *ObjcClassDeclaration(Scope *S, SourceLocation AtClassLoc,