diff --git a/clang/AST/Expr.cpp b/clang/AST/Expr.cpp index 1d2719308523..20f5a0c9d53d 100644 --- a/clang/AST/Expr.cpp +++ b/clang/AST/Expr.cpp @@ -12,15 +12,19 @@ //===----------------------------------------------------------------------===// #include "clang/AST/Expr.h" +#include "clang/Lex/IdentifierTable.h" #include using namespace llvm; using namespace clang; void Expr::dump() const { - if (this == 0) + if (this == 0) { std::cerr << ""; - else - dump_impl(); + return; + } + std::cerr << "("; + dump_impl(); + std::cerr << ")"; } @@ -59,11 +63,55 @@ const char *UnaryOperator::getOpcodeStr(Opcode Op) { } void UnaryOperator::dump_impl() const { - std::cerr << "(" << getOpcodeStr(Opc); + std::cerr << getOpcodeStr(Opc); Input->dump(); +} + + +void ArraySubscriptExpr::dump_impl() const { + Base->dump(); + std::cerr << "["; + Idx->dump(); + std::cerr << "]"; +} + +CallExpr::CallExpr(Expr *fn, Expr **args, unsigned numargs) + : Fn(fn), NumArgs(numargs) { + Args = new Expr*[numargs]; + for (unsigned i = 0; i != numargs; ++i) + Args[i] = args[i]; +} + +void CallExpr::dump_impl() const { + Fn->dump(); + std::cerr << "("; + for (unsigned i = 0, e = getNumArgs(); i != e; ++i) { + if (i) std::cerr << ", "; + getArg(i)->dump(); + } std::cerr << ")"; } +CallExprLOC::CallExprLOC(Expr *Fn, SourceLocation lparenloc, Expr **Args, + unsigned NumArgs, SourceLocation *commalocs, + SourceLocation rparenloc) + : CallExpr(Fn, Args, NumArgs), LParenLoc(lparenloc), RParenLoc(rparenloc) { + unsigned NumCommas = getNumCommas(); + if (NumCommas) + CommaLocs = new SourceLocation[NumCommas]; + else + CommaLocs = 0; + + for (unsigned i = 0; i != NumCommas; ++i) + CommaLocs[i] = commalocs[i]; +} + + +void MemberExpr::dump_impl() const { + Base->dump(); + std::cerr << (isArrow ? "->" : ".") << MemberII->getName(); +} + /// getOpcodeStr - Turn an Opcode enum value into the punctuation char it /// corresponds to, e.g. "<<=". const char *BinaryOperator::getOpcodeStr(Opcode Op) { @@ -103,19 +151,15 @@ const char *BinaryOperator::getOpcodeStr(Opcode Op) { } void BinaryOperator::dump_impl() const { - std::cerr << "("; LHS->dump(); std::cerr << " " << getOpcodeStr(Opc) << " "; RHS->dump(); - std::cerr << ")"; } void ConditionalOperator::dump_impl() const { - std::cerr << "("; Cond->dump(); std::cerr << " ? "; LHS->dump(); std::cerr << " : "; RHS->dump(); - std::cerr << ")"; } diff --git a/clang/AST/Sema.cpp b/clang/AST/Sema.cpp index f411b448d5f8..5b169d6a52f4 100644 --- a/clang/AST/Sema.cpp +++ b/clang/AST/Sema.cpp @@ -51,6 +51,22 @@ public: virtual ExprTy *ParseUnaryOp(const LexerToken &Tok, ExprTy *Input); virtual ExprTy *ParsePostfixUnaryOp(const LexerToken &Tok, ExprTy *Input); + virtual ExprTy *ParseArraySubscriptExpr(ExprTy *Base, SourceLocation LLoc, + ExprTy *Idx, SourceLocation RLoc); + virtual ExprTy *ParseMemberReferenceExpr(ExprTy *Base, SourceLocation OpLoc, + tok::TokenKind OpKind, + SourceLocation MemberLoc, + IdentifierInfo &Member); + + /// ParseCallExpr - Handle a call to Fn with the specified array of arguments. + /// This provides the location of the left/right parens and a list of comma + /// locations. + virtual ExprTy *ParseCallExpr(ExprTy *Fn, SourceLocation LParenLoc, + ExprTy **Args, unsigned NumArgs, + SourceLocation *CommaLocs, + SourceLocation RParenLoc); + + virtual ExprTy *ParseBinOp(const LexerToken &Tok, ExprTy *LHS, ExprTy *RHS); /// ParseConditionalOp - Parse a ?: operation. Note that 'LHS' may be null @@ -162,6 +178,41 @@ ASTBuilder::ExprTy *ASTBuilder::ParsePostfixUnaryOp(const LexerToken &Tok, return new UnaryOperatorLOC(Tok.getLocation(), (Expr*)Input, Opc); } +ASTBuilder::ExprTy *ASTBuilder:: +ParseArraySubscriptExpr(ExprTy *Base, SourceLocation LLoc, + ExprTy *Idx, SourceLocation RLoc) { + if (!FullLocInfo) + return new ArraySubscriptExpr((Expr*)Base, (Expr*)Idx); + else + return new ArraySubscriptExprLOC((Expr*)Base, LLoc, (Expr*)Idx, RLoc); +} + +ASTBuilder::ExprTy *ASTBuilder:: +ParseMemberReferenceExpr(ExprTy *Base, SourceLocation OpLoc, + tok::TokenKind OpKind, SourceLocation MemberLoc, + IdentifierInfo &Member) { + if (!FullLocInfo) + return new MemberExpr((Expr*)Base, OpKind == tok::arrow, Member); + else + return new MemberExprLOC((Expr*)Base, OpLoc, OpKind == tok::arrow, + MemberLoc, Member); +} + +/// ParseCallExpr - Handle a call to Fn with the specified array of arguments. +/// This provides the location of the left/right parens and a list of comma +/// locations. +ASTBuilder::ExprTy *ASTBuilder:: +ParseCallExpr(ExprTy *Fn, SourceLocation LParenLoc, + ExprTy **Args, unsigned NumArgs, + SourceLocation *CommaLocs, SourceLocation RParenLoc) { + if (!FullLocInfo) + return new CallExpr((Expr*)Fn, (Expr**)Args, NumArgs); + else + return new CallExprLOC((Expr*)Fn, LParenLoc, (Expr**)Args, NumArgs, + CommaLocs, RParenLoc); +} + + // Binary Operators. 'Tok' is the token for the operator. ASTBuilder::ExprTy *ASTBuilder::ParseBinOp(const LexerToken &Tok, ExprTy *LHS, ExprTy *RHS) { diff --git a/clang/Parse/ParseExpr.cpp b/clang/Parse/ParseExpr.cpp index 498f18c44934..902a57089505 100644 --- a/clang/Parse/ParseExpr.cpp +++ b/clang/Parse/ParseExpr.cpp @@ -610,10 +610,12 @@ Parser::ExprResult Parser::ParsePostfixExpressionSuffix(ExprResult LHS) { } // Match the ')'. - if (!LHS.isInvalid && ArgExprsOk && Tok.getKind() == tok::r_paren) + if (!LHS.isInvalid && ArgExprsOk && Tok.getKind() == tok::r_paren) { + assert((ArgExprs.size() == 0 || ArgExprs.size()-1 == CommaLocs.size())&& + "Unexpected number of commas!"); LHS = Actions.ParseCallExpr(LHS.Val, Loc, &ArgExprs[0], ArgExprs.size(), - &CommaLocs[0], CommaLocs.size(), - Tok.getLocation()); + &CommaLocs[0], Tok.getLocation()); + } MatchRHSPunctuation(tok::r_paren, Loc); break; diff --git a/clang/Sema/Sema.cpp b/clang/Sema/Sema.cpp index f411b448d5f8..5b169d6a52f4 100644 --- a/clang/Sema/Sema.cpp +++ b/clang/Sema/Sema.cpp @@ -51,6 +51,22 @@ public: virtual ExprTy *ParseUnaryOp(const LexerToken &Tok, ExprTy *Input); virtual ExprTy *ParsePostfixUnaryOp(const LexerToken &Tok, ExprTy *Input); + virtual ExprTy *ParseArraySubscriptExpr(ExprTy *Base, SourceLocation LLoc, + ExprTy *Idx, SourceLocation RLoc); + virtual ExprTy *ParseMemberReferenceExpr(ExprTy *Base, SourceLocation OpLoc, + tok::TokenKind OpKind, + SourceLocation MemberLoc, + IdentifierInfo &Member); + + /// ParseCallExpr - Handle a call to Fn with the specified array of arguments. + /// This provides the location of the left/right parens and a list of comma + /// locations. + virtual ExprTy *ParseCallExpr(ExprTy *Fn, SourceLocation LParenLoc, + ExprTy **Args, unsigned NumArgs, + SourceLocation *CommaLocs, + SourceLocation RParenLoc); + + virtual ExprTy *ParseBinOp(const LexerToken &Tok, ExprTy *LHS, ExprTy *RHS); /// ParseConditionalOp - Parse a ?: operation. Note that 'LHS' may be null @@ -162,6 +178,41 @@ ASTBuilder::ExprTy *ASTBuilder::ParsePostfixUnaryOp(const LexerToken &Tok, return new UnaryOperatorLOC(Tok.getLocation(), (Expr*)Input, Opc); } +ASTBuilder::ExprTy *ASTBuilder:: +ParseArraySubscriptExpr(ExprTy *Base, SourceLocation LLoc, + ExprTy *Idx, SourceLocation RLoc) { + if (!FullLocInfo) + return new ArraySubscriptExpr((Expr*)Base, (Expr*)Idx); + else + return new ArraySubscriptExprLOC((Expr*)Base, LLoc, (Expr*)Idx, RLoc); +} + +ASTBuilder::ExprTy *ASTBuilder:: +ParseMemberReferenceExpr(ExprTy *Base, SourceLocation OpLoc, + tok::TokenKind OpKind, SourceLocation MemberLoc, + IdentifierInfo &Member) { + if (!FullLocInfo) + return new MemberExpr((Expr*)Base, OpKind == tok::arrow, Member); + else + return new MemberExprLOC((Expr*)Base, OpLoc, OpKind == tok::arrow, + MemberLoc, Member); +} + +/// ParseCallExpr - Handle a call to Fn with the specified array of arguments. +/// This provides the location of the left/right parens and a list of comma +/// locations. +ASTBuilder::ExprTy *ASTBuilder:: +ParseCallExpr(ExprTy *Fn, SourceLocation LParenLoc, + ExprTy **Args, unsigned NumArgs, + SourceLocation *CommaLocs, SourceLocation RParenLoc) { + if (!FullLocInfo) + return new CallExpr((Expr*)Fn, (Expr**)Args, NumArgs); + else + return new CallExprLOC((Expr*)Fn, LParenLoc, (Expr**)Args, NumArgs, + CommaLocs, RParenLoc); +} + + // Binary Operators. 'Tok' is the token for the operator. ASTBuilder::ExprTy *ASTBuilder::ParseBinOp(const LexerToken &Tok, ExprTy *LHS, ExprTy *RHS) { diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h index 34dfd8991c74..e84a75243e38 100644 --- a/clang/include/clang/AST/Expr.h +++ b/clang/include/clang/AST/Expr.h @@ -15,9 +15,11 @@ #define LLVM_CLANG_AST_EXPR_H #include "clang/Basic/SourceLocation.h" +#include namespace llvm { namespace clang { + class IdentifierInfo; /// Expr - This represents one expression etc. /// @@ -97,6 +99,88 @@ public: }; +/// ArraySubscriptExpr - [C99 6.5.2.1] Array Subscripting. +class ArraySubscriptExpr : public Expr { + Expr *Base, *Idx; +public: + ArraySubscriptExpr(Expr *base, Expr *idx) : Base(base), Idx(idx) {} + + virtual void dump_impl() const; +}; + + +class ArraySubscriptExprLOC : public ArraySubscriptExpr { + SourceLocation LLoc, RLoc; +public: + ArraySubscriptExprLOC(Expr *Base, SourceLocation lloc, Expr *Idx, + SourceLocation rloc) + : ArraySubscriptExpr(Base, Idx), LLoc(lloc), RLoc(rloc) {} +}; + +/// CallExpr - [C99 6.5.2.2] Function Calls. +/// +class CallExpr : public Expr { + Expr *Fn; + Expr **Args; + unsigned NumArgs; +public: + CallExpr(Expr *fn, Expr **args, unsigned numargs); + ~CallExpr() { + delete [] Args; + } + + /// getNumArgs - Return the number of actual arguments to this call. + /// + unsigned getNumArgs() const { return NumArgs; } + + /// getArg - Return the specified argument. + Expr *getArg(unsigned Arg) const { + assert(Arg < NumArgs && "Arg access out of range!"); + return Args[Arg]; + } + + /// getNumCommas - Return the number of commas that must have been present in + /// this function call. + unsigned getNumCommas() const { return NumArgs ? NumArgs - 1 : 0; } + + virtual void dump_impl() const; +}; + +class CallExprLOC : public CallExpr { + SourceLocation LParenLoc, RParenLoc; + SourceLocation *CommaLocs; +public: + CallExprLOC(Expr *Fn, SourceLocation lparenloc, Expr **Args, unsigned NumArgs, + SourceLocation *commalocs, SourceLocation rparenloc); + ~CallExprLOC() { + delete [] CommaLocs; + } +}; + +/// MemberExpr - [C99 6.5.2.3] Structure and Union Members. +/// +class MemberExpr : public Expr { + Expr *Base; + // TODO: union { Decl *MemberDecl; IdentifierInfo *MemberII; }; + IdentifierInfo *MemberII; + bool isArrow; // True if this is "X->F", false if this is "X.F". +public: + MemberExpr(Expr *base, bool isarrow, IdentifierInfo &memberii) + : Base(base), MemberII(&memberii), isArrow(isarrow) { + } + virtual void dump_impl() const; +}; + +class MemberExprLOC : public MemberExpr { + SourceLocation OpLoc, MemberLoc; +public: + MemberExprLOC(Expr *Base, SourceLocation oploc, bool isArrow, + SourceLocation memberLoc, IdentifierInfo &MemberII) + : MemberExpr(Base, isArrow, MemberII), OpLoc(oploc), MemberLoc(memberLoc) { + } + +}; + class BinaryOperator : public Expr { public: enum Opcode { diff --git a/clang/include/clang/Parse/Action.h b/clang/include/clang/Parse/Action.h index 58c24b08d6c2..1182ad4ed24d 100644 --- a/clang/include/clang/Parse/Action.h +++ b/clang/include/clang/Parse/Action.h @@ -100,10 +100,11 @@ public: /// ParseCallExpr - Handle a call to Fn with the specified array of arguments. /// This provides the location of the left/right parens and a list of comma - /// locations. + /// locations. There are guaranteed to be one fewer commas than arguments, + /// unless there are zero arguments. virtual ExprTy *ParseCallExpr(ExprTy *Fn, SourceLocation LParenLoc, ExprTy **Args, unsigned NumArgs, - SourceLocation *CommaLocs, unsigned NumCommas, + SourceLocation *CommaLocs, SourceLocation RParenLoc) { return 0; }