diff options
Diffstat (limited to 'include/clang/AST/Expr.h')
-rw-r--r-- | include/clang/AST/Expr.h | 596 |
1 files changed, 596 insertions, 0 deletions
diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h new file mode 100644 index 0000000000..fcf179e565 --- /dev/null +++ b/include/clang/AST/Expr.h @@ -0,0 +1,596 @@ +//===--- Expr.h - Classes for representing expressions ----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by Chris Lattner and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the Expr interface and subclasses. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_EXPR_H +#define LLVM_CLANG_AST_EXPR_H + +#include "clang/AST/Stmt.h" +#include "clang/AST/Type.h" +#include "clang/AST/Decl.h" +#include "llvm/ADT/APSInt.h" + +namespace clang { + class IdentifierInfo; + class Decl; + +/// 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 +/// is required. +/// +class Expr : public Stmt { + QualType TR; +protected: + Expr(StmtClass SC, QualType T) : Stmt(SC), TR(T) {} + ~Expr() {} +public: + QualType getType() const { return TR; } + + /// SourceLocation tokens are not useful in isolation - they are low level + /// value objects created/interpreted by SourceManager. We assume AST + /// clients will have a pointer to the respective SourceManager. + virtual SourceRange getSourceRange() const = 0; + SourceLocation getLocStart() const { return getSourceRange().Begin(); } + SourceLocation getLocEnd() const { return getSourceRange().End(); } + + /// getExprLoc - Return the preferred location for the arrow when diagnosing + /// a problem with a generic expression. + virtual SourceLocation getExprLoc() const { return getLocStart(); } + + /// hasLocalSideEffect - Return true if this immediate expression has side + /// effects, not counting any sub-expressions. + bool hasLocalSideEffect() const; + + /// isLvalue - C99 6.3.2.1: an lvalue is an expression with an object type or + /// incomplete type other than void. Nonarray expressions that can be lvalues: + /// - name, where name must be a variable + /// - e[i] + /// - (e), where e must be an lvalue + /// - e.name, where e must be an lvalue + /// - e->name + /// - *e, the type of e cannot be a function type + /// - string-constant + /// + enum isLvalueResult { + LV_Valid, + LV_NotObjectType, + LV_IncompleteVoidType, + LV_InvalidExpression + }; + isLvalueResult isLvalue(); + + /// isModifiableLvalue - C99 6.3.2.1: an lvalue that does not have array type, + /// does not have an incomplete type, does not have a const-qualified type, + /// and if it is a structure or union, does not have any member (including, + /// recursively, any member or element of all contained aggregates or unions) + /// with a const-qualified type. + enum isModifiableLvalueResult { + MLV_Valid, + MLV_NotObjectType, + MLV_IncompleteVoidType, + MLV_InvalidExpression, + MLV_IncompleteType, + MLV_ConstQualified, + MLV_ArrayType + }; + isModifiableLvalueResult isModifiableLvalue(); + + bool isNullPointerConstant() const; + + /// isIntegerConstantExpr - Return true if this expression is a valid integer + /// constant expression, and, if so, return its value in Result. If not a + /// valid i-c-e, return false and fill in Loc (if specified) with the location + /// of the invalid expression. + bool isIntegerConstantExpr(llvm::APSInt &Result, SourceLocation *Loc = 0, + bool isEvaluated = true) const; + bool isIntegerConstantExpr(SourceLocation *Loc = 0) const { + llvm::APSInt X(32); + return isIntegerConstantExpr(X, Loc); + } + + virtual void visit(StmtVisitor &Visitor); + static bool classof(const Stmt *T) { + return T->getStmtClass() >= firstExprConstant && + T->getStmtClass() <= lastExprConstant; + } + static bool classof(const Expr *) { return true; } +}; + +//===----------------------------------------------------------------------===// +// Primary Expressions. +//===----------------------------------------------------------------------===// + +/// DeclRefExpr - [C99 6.5.1p2] - A reference to a declared variable, function, +/// enum, etc. +class DeclRefExpr : public Expr { + Decl *D; // a ValueDecl or EnumConstantDecl + SourceLocation Loc; +public: + DeclRefExpr(Decl *d, QualType t, SourceLocation l) : + Expr(DeclRefExprClass, t), D(d), Loc(l) {} + + Decl *getDecl() { return D; } + const Decl *getDecl() const { return D; } + virtual SourceRange getSourceRange() const { return SourceRange(Loc); } + + + virtual void visit(StmtVisitor &Visitor); + static bool classof(const Stmt *T) { + return T->getStmtClass() == DeclRefExprClass; + } + static bool classof(const DeclRefExpr *) { return true; } +}; + +class IntegerLiteral : public Expr { + llvm::APInt Value; + SourceLocation Loc; +public: + // type should be IntTy, LongTy, LongLongTy, UnsignedIntTy, UnsignedLongTy, + // or UnsignedLongLongTy + IntegerLiteral(const llvm::APInt &V, QualType type, SourceLocation l) + : Expr(IntegerLiteralClass, type), Value(V), Loc(l) { + assert(type->isIntegerType() && "Illegal type in IntegerLiteral"); + } + const llvm::APInt &getValue() const { return Value; } + virtual SourceRange getSourceRange() const { return SourceRange(Loc); } + + virtual void visit(StmtVisitor &Visitor); + static bool classof(const Stmt *T) { + return T->getStmtClass() == IntegerLiteralClass; + } + static bool classof(const IntegerLiteral *) { return true; } +}; + +class CharacterLiteral : public Expr { + unsigned Value; + SourceLocation Loc; +public: + // type should be IntTy + CharacterLiteral(unsigned value, QualType type, SourceLocation l) + : Expr(CharacterLiteralClass, type), Value(value), Loc(l) { + } + virtual SourceRange getSourceRange() const { return SourceRange(Loc); } + + unsigned getValue() const { return Value; } + + virtual void visit(StmtVisitor &Visitor); + static bool classof(const Stmt *T) { + return T->getStmtClass() == CharacterLiteralClass; + } + static bool classof(const CharacterLiteral *) { return true; } +}; + +class FloatingLiteral : public Expr { + float Value; // FIXME + SourceLocation Loc; +public: + FloatingLiteral(float value, QualType type, SourceLocation l) + : Expr(FloatingLiteralClass, type), Value(value), Loc(l) {} + + float getValue() const { return Value; } + + virtual SourceRange getSourceRange() const { return SourceRange(Loc); } + + virtual void visit(StmtVisitor &Visitor); + static bool classof(const Stmt *T) { + return T->getStmtClass() == FloatingLiteralClass; + } + static bool classof(const FloatingLiteral *) { return true; } +}; + +class StringLiteral : public Expr { + const char *StrData; + unsigned ByteLength; + bool IsWide; + // if the StringLiteral was composed using token pasting, both locations + // are needed. If not (the common case), firstTokLoc == lastTokLoc. + // FIXME: if space becomes an issue, we should create a sub-class. + SourceLocation firstTokLoc, lastTokLoc; +public: + StringLiteral(const char *strData, unsigned byteLength, bool Wide, + QualType t, SourceLocation b, SourceLocation e); + virtual ~StringLiteral(); + + const char *getStrData() const { return StrData; } + unsigned getByteLength() const { return ByteLength; } + bool isWide() const { return IsWide; } + + virtual SourceRange getSourceRange() const { + return SourceRange(firstTokLoc,lastTokLoc); + } + virtual void visit(StmtVisitor &Visitor); + static bool classof(const Stmt *T) { + return T->getStmtClass() == StringLiteralClass; + } + static bool classof(const StringLiteral *) { return true; } +}; + +/// ParenExpr - This represents a parethesized expression, e.g. "(1)". This +/// AST node is only formed if full location information is requested. +class ParenExpr : public Expr { + SourceLocation L, R; + Expr *Val; +public: + ParenExpr(SourceLocation l, SourceLocation r, Expr *val) + : Expr(ParenExprClass, val->getType()), L(l), R(r), Val(val) {} + + const Expr *getSubExpr() const { return Val; } + Expr *getSubExpr() { return Val; } + SourceRange getSourceRange() const { return SourceRange(L, R); } + + virtual void visit(StmtVisitor &Visitor); + static bool classof(const Stmt *T) { + return T->getStmtClass() == ParenExprClass; + } + static bool classof(const ParenExpr *) { return true; } +}; + + +/// UnaryOperator - This represents the unary-expression's (except sizeof of +/// types), the postinc/postdec operators from postfix-expression, and various +/// extensions. +class UnaryOperator : public Expr { +public: + enum Opcode { + PostInc, PostDec, // [C99 6.5.2.4] Postfix increment and decrement operators + PreInc, PreDec, // [C99 6.5.3.1] Prefix increment and decrement operators. + AddrOf, Deref, // [C99 6.5.3.2] Address and indirection operators. + Plus, Minus, // [C99 6.5.3.3] Unary arithmetic operators. + Not, LNot, // [C99 6.5.3.3] Unary arithmetic operators. + SizeOf, AlignOf, // [C99 6.5.3.4] Sizeof (expr, not type) operator. + Real, Imag, // "__real expr"/"__imag expr" Extension. + Extension // __extension__ marker. + }; +private: + Expr *Val; + Opcode Opc; + SourceLocation Loc; +public: + + UnaryOperator(Expr *input, Opcode opc, QualType type, SourceLocation l) + : Expr(UnaryOperatorClass, type), Val(input), Opc(opc), Loc(l) {} + + Opcode getOpcode() const { return Opc; } + Expr *getSubExpr() const { return Val; } + + /// getOperatorLoc - Return the location of the operator. + SourceLocation getOperatorLoc() const { return Loc; } + + /// isPostfix - Return true if this is a postfix operation, like x++. + static bool isPostfix(Opcode Op); + + bool isPostfix() const { return isPostfix(Opc); } + bool isIncrementDecrementOp() const { return Opc>=PostInc && Opc<=PreDec; } + bool isSizeOfAlignOfOp() const { return Opc == SizeOf || Opc == AlignOf; } + static bool isArithmeticOp(Opcode Op) { return Op >= Plus && Op <= LNot; } + + /// getDecl - a recursive routine that derives the base decl for an + /// expression. For example, it will return the declaration for "s" from + /// the following complex expression "s.zz[2].bb.vv". + static bool isAddressable(Expr *e); + + /// getOpcodeStr - Turn an Opcode enum value into the punctuation char it + /// corresponds to, e.g. "sizeof" or "[pre]++" + static const char *getOpcodeStr(Opcode Op); + + virtual SourceRange getSourceRange() const { + if (isPostfix()) + return SourceRange(Val->getLocStart(), Loc); + else + return SourceRange(Loc, Val->getLocEnd()); + } + virtual SourceLocation getExprLoc() const { return Loc; } + + virtual void visit(StmtVisitor &Visitor); + static bool classof(const Stmt *T) { + return T->getStmtClass() == UnaryOperatorClass; + } + static bool classof(const UnaryOperator *) { return true; } +}; + +/// SizeOfAlignOfTypeExpr - [C99 6.5.3.4] - This is only for sizeof/alignof of +/// *types*. sizeof(expr) is handled by UnaryOperator. +class SizeOfAlignOfTypeExpr : public Expr { + bool isSizeof; // true if sizeof, false if alignof. + QualType Ty; + SourceLocation OpLoc, RParenLoc; +public: + SizeOfAlignOfTypeExpr(bool issizeof, QualType argType, QualType resultType, + SourceLocation op, SourceLocation rp) : + Expr(SizeOfAlignOfTypeExprClass, resultType), + isSizeof(issizeof), Ty(argType), OpLoc(op), RParenLoc(rp) {} + + bool isSizeOf() const { return isSizeof; } + QualType getArgumentType() const { return Ty; } + SourceRange getSourceRange() const { return SourceRange(OpLoc, RParenLoc); } + + virtual void visit(StmtVisitor &Visitor); + static bool classof(const Stmt *T) { + return T->getStmtClass() == SizeOfAlignOfTypeExprClass; + } + static bool classof(const SizeOfAlignOfTypeExpr *) { return true; } +}; + +//===----------------------------------------------------------------------===// +// Postfix Operators. +//===----------------------------------------------------------------------===// + +/// ArraySubscriptExpr - [C99 6.5.2.1] Array Subscripting. +class ArraySubscriptExpr : public Expr { + Expr *Base, *Idx; + SourceLocation RBracketLoc; +public: + ArraySubscriptExpr(Expr *base, Expr *idx, QualType t, + SourceLocation rbracketloc) : + Expr(ArraySubscriptExprClass, t), + Base(base), Idx(idx), RBracketLoc(rbracketloc) {} + + Expr *getBase() { return Base; } + const Expr *getBase() const { return Base; } + Expr *getIdx() { return Idx; } + const Expr *getIdx() const { return Idx; } + + SourceRange getSourceRange() const { + return SourceRange(Base->getLocStart(), RBracketLoc); + } + virtual SourceLocation getExprLoc() const { return RBracketLoc; } + + virtual void visit(StmtVisitor &Visitor); + static bool classof(const Stmt *T) { + return T->getStmtClass() == ArraySubscriptExprClass; + } + static bool classof(const ArraySubscriptExpr *) { return true; } +}; + + +/// CallExpr - [C99 6.5.2.2] Function Calls. +/// +class CallExpr : public Expr { + Expr *Fn; + Expr **Args; + unsigned NumArgs; + SourceLocation RParenLoc; +public: + CallExpr(Expr *fn, Expr **args, unsigned numargs, QualType t, + SourceLocation rparenloc); + ~CallExpr() { + delete [] Args; + } + + const Expr *getCallee() const { return Fn; } + Expr *getCallee() { return Fn; } + + /// 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 Args[Arg]; + } + const 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; } + + SourceRange getSourceRange() const { + return SourceRange(Fn->getLocStart(), RParenLoc); + } + + virtual void visit(StmtVisitor &Visitor); + static bool classof(const Stmt *T) { + return T->getStmtClass() == CallExprClass; + } + static bool classof(const CallExpr *) { return true; } +}; + +/// MemberExpr - [C99 6.5.2.3] Structure and Union Members. +/// +class MemberExpr : public Expr { + Expr *Base; + FieldDecl *MemberDecl; + SourceLocation MemberLoc; + bool IsArrow; // True if this is "X->F", false if this is "X.F". +public: + MemberExpr(Expr *base, bool isarrow, FieldDecl *memberdecl, SourceLocation l) + : Expr(MemberExprClass, memberdecl->getType()), + Base(base), MemberDecl(memberdecl), MemberLoc(l), IsArrow(isarrow) {} + + Expr *getBase() const { return Base; } + FieldDecl *getMemberDecl() const { return MemberDecl; } + bool isArrow() const { return IsArrow; } + + virtual SourceRange getSourceRange() const { + return SourceRange(getBase()->getLocStart(), MemberLoc); + } + virtual SourceLocation getExprLoc() const { return MemberLoc; } + + virtual void visit(StmtVisitor &Visitor); + static bool classof(const Stmt *T) { + return T->getStmtClass() == MemberExprClass; + } + static bool classof(const MemberExpr *) { return true; } +}; + +/// CastExpr - [C99 6.5.4] Cast Operators. +/// +class CastExpr : public Expr { + QualType Ty; + Expr *Op; + SourceLocation Loc; // the location of the left paren +public: + CastExpr(QualType ty, Expr *op, SourceLocation l) : + Expr(CastExprClass, ty), Ty(ty), Op(op), Loc(l) {} + CastExpr(StmtClass SC, QualType ty, Expr *op) : + Expr(SC, QualType()), Ty(ty), Op(op), Loc(SourceLocation()) {} + + SourceLocation getLParenLoc() const { return Loc; } + + QualType getDestType() const { return Ty; } + Expr *getSubExpr() const { return Op; } + + virtual SourceRange getSourceRange() const { + return SourceRange(Loc, getSubExpr()->getSourceRange().End()); + } + virtual void visit(StmtVisitor &Visitor); + static bool classof(const Stmt *T) { + return T->getStmtClass() == CastExprClass; + } + static bool classof(const CastExpr *) { return true; } +}; + + +class BinaryOperator : public Expr { +public: + enum Opcode { + // Operators listed in order of precedence. + Mul, Div, Rem, // [C99 6.5.5] Multiplicative operators. + Add, Sub, // [C99 6.5.6] Additive operators. + Shl, Shr, // [C99 6.5.7] Bitwise shift operators. + LT, GT, LE, GE, // [C99 6.5.8] Relational operators. + EQ, NE, // [C99 6.5.9] Equality operators. + And, // [C99 6.5.10] Bitwise AND operator. + Xor, // [C99 6.5.11] Bitwise XOR operator. + Or, // [C99 6.5.12] Bitwise OR operator. + LAnd, // [C99 6.5.13] Logical AND operator. + LOr, // [C99 6.5.14] Logical OR operator. + Assign, MulAssign,// [C99 6.5.16] Assignment operators. + DivAssign, RemAssign, + AddAssign, SubAssign, + ShlAssign, ShrAssign, + AndAssign, XorAssign, + OrAssign, + Comma // [C99 6.5.17] Comma operator. + }; + + BinaryOperator(Expr *lhs, Expr *rhs, Opcode opc, QualType ResTy) + : Expr(BinaryOperatorClass, ResTy), LHS(lhs), RHS(rhs), Opc(opc) { + assert(!isCompoundAssignmentOp() && + "Use ArithAssignBinaryOperator for compound assignments"); + } + + Opcode getOpcode() const { return Opc; } + Expr *getLHS() const { return LHS; } + Expr *getRHS() const { return RHS; } + virtual SourceRange getSourceRange() const { + return SourceRange(getLHS()->getLocStart(), getRHS()->getLocEnd()); + } + + /// getOpcodeStr - Turn an Opcode enum value into the punctuation char it + /// corresponds to, e.g. "<<=". + static const char *getOpcodeStr(Opcode Op); + + /// predicates to categorize the respective opcodes. + bool isMultiplicativeOp() const { return Opc >= Mul && Opc <= Rem; } + bool isAdditiveOp() const { return Opc == Add || Opc == Sub; } + bool isShiftOp() const { return Opc == Shl || Opc == Shr; } + bool isBitwiseOp() const { return Opc >= And && Opc <= Or; } + bool isRelationalOp() const { return Opc >= LT && Opc <= GE; } + bool isEqualityOp() const { return Opc == EQ || Opc == NE; } + bool isLogicalOp() const { return Opc == LAnd || Opc == LOr; } + bool isAssignmentOp() const { return Opc >= Assign && Opc <= OrAssign; } + bool isCompoundAssignmentOp() const { return Opc > Assign && Opc <= OrAssign;} + bool isShiftAssignOp() const { return Opc == ShlAssign || Opc == ShrAssign; } + + virtual void visit(StmtVisitor &Visitor); + static bool classof(const Stmt *T) { + return T->getStmtClass() == BinaryOperatorClass; + } + static bool classof(const BinaryOperator *) { return true; } +private: + Expr *LHS, *RHS; + Opcode Opc; +protected: + BinaryOperator(Expr *lhs, Expr *rhs, Opcode opc, QualType ResTy, bool dead) + : Expr(BinaryOperatorClass, ResTy), LHS(lhs), RHS(rhs), Opc(opc) { + } +}; + +/// CompoundAssignOperator - For compound assignments (e.g. +=), we keep +/// track of the type the operation is performed in. Due to the semantics of +/// these operators, the operands are promoted, the aritmetic performed, an +/// implicit conversion back to the result type done, then the assignment takes +/// place. This captures the intermediate type which the computation is done +/// in. +class CompoundAssignOperator : public BinaryOperator { + QualType ComputationType; +public: + CompoundAssignOperator(Expr *lhs, Expr *rhs, Opcode opc, + QualType ResType, QualType CompType) + : BinaryOperator(lhs, rhs, opc, ResType, true), ComputationType(CompType) { + assert(isCompoundAssignmentOp() && + "Only should be used for compound assignments"); + } + + QualType getComputationType() const { return ComputationType; } + + static bool classof(const CompoundAssignOperator *) { return true; } + static bool classof(const BinaryOperator *B) { + return B->isCompoundAssignmentOp(); + } + static bool classof(const Stmt *S) { + return isa<BinaryOperator>(S) && classof(cast<BinaryOperator>(S)); + } +}; + +/// ConditionalOperator - The ?: operator. Note that LHS may be null when the +/// GNU "missing LHS" extension is in use. +/// +class ConditionalOperator : public Expr { + Expr *Cond, *LHS, *RHS; // Left/Middle/Right hand sides. +public: + ConditionalOperator(Expr *cond, Expr *lhs, Expr *rhs, QualType t) + : Expr(ConditionalOperatorClass, t), Cond(cond), LHS(lhs), RHS(rhs) {} + + Expr *getCond() const { return Cond; } + Expr *getLHS() const { return LHS; } + Expr *getRHS() const { return RHS; } + + virtual SourceRange getSourceRange() const { + return SourceRange(getCond()->getLocStart(), getRHS()->getLocEnd()); + } + virtual void visit(StmtVisitor &Visitor); + static bool classof(const Stmt *T) { + return T->getStmtClass() == ConditionalOperatorClass; + } + static bool classof(const ConditionalOperator *) { return true; } +}; + +/// AddrLabel - The GNU address of label extension, representing &&label. +class AddrLabel : public Expr { + SourceLocation AmpAmpLoc, LabelLoc; + LabelStmt *Label; +public: + AddrLabel(SourceLocation AALoc, SourceLocation LLoc, LabelStmt *L, QualType t) + : Expr(AddrLabelClass, t), AmpAmpLoc(AALoc), LabelLoc(LLoc), Label(L) {} + + virtual SourceRange getSourceRange() const { + return SourceRange(AmpAmpLoc, LabelLoc); + } + + LabelStmt *getLabel() const { return Label; } + + virtual void visit(StmtVisitor &Visitor); + static bool classof(const Stmt *T) { + return T->getStmtClass() == AddrLabelClass; + } + static bool classof(const AddrLabel *) { return true; } +}; + +} // end namespace clang + +#endif |