Index: include/clang/AST/Expr.h =================================================================== --- include/clang/AST/Expr.h +++ include/clang/AST/Expr.h @@ -2311,28 +2311,32 @@ /// ArraySubscriptExpr - [C99 6.5.2.1] Array Subscripting. class ArraySubscriptExpr : public Expr { - enum { LHS, RHS, END_EXPR=2 }; - Stmt* SubExprs[END_EXPR]; - SourceLocation RBracketLoc; + friend class ASTStmtReader; + + enum { LHS, RHS, END_EXPR }; + Stmt *SubExprs[END_EXPR]; + + void setLhsIsBase(bool B) { ArraySubscriptExprBits.LhsIsBase = B; } + public: - ArraySubscriptExpr(Expr *lhs, Expr *rhs, QualType t, - ExprValueKind VK, ExprObjectKind OK, - SourceLocation rbracketloc) - : Expr(ArraySubscriptExprClass, t, VK, OK, - lhs->isTypeDependent() || rhs->isTypeDependent(), - lhs->isValueDependent() || rhs->isValueDependent(), - (lhs->isInstantiationDependent() || - rhs->isInstantiationDependent()), - (lhs->containsUnexpandedParameterPack() || - rhs->containsUnexpandedParameterPack())), - RBracketLoc(rbracketloc) { - SubExprs[LHS] = lhs; - SubExprs[RHS] = rhs; + ArraySubscriptExpr(Expr *Lhs, Expr *Rhs, QualType Ty, ExprValueKind VK, + ExprObjectKind OK, SourceLocation RBracketLoc) + : Expr(ArraySubscriptExprClass, Ty, VK, OK, + Lhs->isTypeDependent() || Rhs->isTypeDependent(), + Lhs->isValueDependent() || Rhs->isValueDependent(), + (Lhs->isInstantiationDependent() || + Rhs->isInstantiationDependent()), + (Lhs->containsUnexpandedParameterPack() || + Rhs->containsUnexpandedParameterPack())) { + setLHS(Lhs); + setRHS(Rhs); + setLhsIsBase(Rhs->getType()->isIntegerType()); + setRBracketLoc(RBracketLoc); } /// Create an empty array subscript expression. explicit ArraySubscriptExpr(EmptyShell Shell) - : Expr(ArraySubscriptExprClass, Shell) { } + : Expr(ArraySubscriptExprClass, Shell) {} /// An array access can be written A[4] or 4[A] (both are equivalent). /// - getBase() and getIdx() always present the normalized view: A[4]. @@ -2343,6 +2347,8 @@ /// predicate the format conversion in getBase and getIdx only on the /// the type of the RHS, as it is possible for the LHS to be a vector of /// integer type + bool lhsIsBase() const { return ArraySubscriptExprBits.LhsIsBase; } + Expr *getLHS() { return cast(SubExprs[LHS]); } const Expr *getLHS() const { return cast(SubExprs[LHS]); } void setLHS(Expr *E) { SubExprs[LHS] = E; } @@ -2351,29 +2357,23 @@ const Expr *getRHS() const { return cast(SubExprs[RHS]); } void setRHS(Expr *E) { SubExprs[RHS] = E; } - Expr *getBase() { - return getRHS()->getType()->isIntegerType() ? getLHS() : getRHS(); - } - - const Expr *getBase() const { - return getRHS()->getType()->isIntegerType() ? getLHS() : getRHS(); - } - - Expr *getIdx() { - return getRHS()->getType()->isIntegerType() ? getRHS() : getLHS(); - } + Expr *getBase() { return lhsIsBase() ? getLHS() : getRHS(); } + const Expr *getBase() const { return lhsIsBase() ? getLHS() : getRHS(); } - const Expr *getIdx() const { - return getRHS()->getType()->isIntegerType() ? getRHS() : getLHS(); - } + Expr *getIdx() { return lhsIsBase() ? getRHS() : getLHS(); } + const Expr *getIdx() const { return lhsIsBase() ? getRHS() : getLHS(); } SourceLocation getBeginLoc() const LLVM_READONLY { return getLHS()->getBeginLoc(); } - SourceLocation getEndLoc() const LLVM_READONLY { return RBracketLoc; } + SourceLocation getEndLoc() const { return getRBracketLoc(); } - SourceLocation getRBracketLoc() const { return RBracketLoc; } - void setRBracketLoc(SourceLocation L) { RBracketLoc = L; } + SourceLocation getRBracketLoc() const { + return ArraySubscriptExprBits.RBracketLoc; + } + void setRBracketLoc(SourceLocation L) { + ArraySubscriptExprBits.RBracketLoc = L; + } SourceLocation getExprLoc() const LLVM_READONLY { return getBase()->getExprLoc(); @@ -2385,7 +2385,7 @@ // Iterators child_range children() { - return child_range(&SubExprs[0], &SubExprs[0]+END_EXPR); + return child_range(&SubExprs[0], &SubExprs[0] + END_EXPR); } const_child_range children() const { return const_child_range(&SubExprs[0], &SubExprs[0] + END_EXPR); @@ -2401,8 +2401,6 @@ class CallExpr : public Expr { enum { FN=0, PREARGS_START=1 }; Stmt **SubExprs; - unsigned NumArgs; - SourceLocation RParenLoc; void updateDependenciesFromArg(Expr *Arg); @@ -2454,8 +2452,7 @@ } /// getNumArgs - Return the number of actual arguments to this call. - /// - unsigned getNumArgs() const { return NumArgs; } + unsigned getNumArgs() const { return CallExprBits.NumArgs; } /// Retrieve the call arguments. Expr **getArgs() { @@ -2468,17 +2465,17 @@ /// getArg - Return the specified argument. Expr *getArg(unsigned Arg) { - assert(Arg < NumArgs && "Arg access out of range!"); + assert(Arg < getNumArgs() && "Arg access out of range!"); return cast_or_null(SubExprs[Arg + getNumPreArgs() + PREARGS_START]); } const Expr *getArg(unsigned Arg) const { - assert(Arg < NumArgs && "Arg access out of range!"); + assert(Arg < getNumArgs() && "Arg access out of range!"); return cast_or_null(SubExprs[Arg + getNumPreArgs() + PREARGS_START]); } /// setArg - Set the specified argument. void setArg(unsigned Arg, Expr *ArgExpr) { - assert(Arg < NumArgs && "Arg access out of range!"); + assert(Arg < getNumArgs() && "Arg access out of range!"); SubExprs[Arg+getNumPreArgs()+PREARGS_START] = ArgExpr; } @@ -2519,7 +2516,7 @@ /// getNumCommas - Return the number of commas that must have been present in /// this function call. - unsigned getNumCommas() const { return NumArgs ? NumArgs - 1 : 0; } + unsigned getNumCommas() const { return getNumArgs() ? getNumArgs() - 1 : 0; } /// getBuiltinCallee - If this is a call to a builtin, return the builtin ID /// of the callee. If not, return 0. @@ -2534,8 +2531,8 @@ /// type. QualType getCallReturnType(const ASTContext &Ctx) const; - SourceLocation getRParenLoc() const { return RParenLoc; } - void setRParenLoc(SourceLocation L) { RParenLoc = L; } + SourceLocation getRParenLoc() const { return CallExprBits.RParenLoc; } + void setRParenLoc(SourceLocation L) { CallExprBits.RParenLoc = L; } SourceLocation getBeginLoc() const LLVM_READONLY; SourceLocation getEndLoc() const LLVM_READONLY; @@ -2557,12 +2554,12 @@ // Iterators child_range children() { - return child_range(&SubExprs[0], - &SubExprs[0]+NumArgs+getNumPreArgs()+PREARGS_START); + return child_range(&SubExprs[0], &SubExprs[0] + getNumArgs() + + getNumPreArgs() + PREARGS_START); } const_child_range children() const { - return const_child_range(&SubExprs[0], &SubExprs[0] + NumArgs + + return const_child_range(&SubExprs[0], &SubExprs[0] + getNumArgs() + getNumPreArgs() + PREARGS_START); } }; Index: include/clang/AST/Stmt.h =================================================================== --- include/clang/AST/Stmt.h +++ include/clang/AST/Stmt.h @@ -395,6 +395,22 @@ unsigned IsType : 1; // true if operand is a type, false if an expression. }; + class ArraySubscriptExprBitfields { + friend class ArraySubscriptExpr; + friend class ASTStmtReader; + + unsigned : NumExprBits; + + /// True if the expression is of the form A[4], that is + /// getLHS() == getBase(). False if the the expression is of the + /// form 4[A], that is getRHS() == getBase(). See the comment + /// above ArraySubscriptExpr::lhsIsBase. + unsigned LhsIsBase : 1; + + /// The location of the right bracket. + SourceLocation RBracketLoc; + }; + class DeclRefExprBitfields { friend class ASTStmtReader; // deserialization friend class DeclRefExpr; @@ -431,6 +447,9 @@ unsigned : NumExprBits; unsigned NumPreArgs : 1; + unsigned NumArgs : 14; + + SourceLocation RParenLoc; }; class MemberExprBitfields { @@ -590,6 +609,7 @@ CharacterLiteralBitfields CharacterLiteralBits; FloatingLiteralBitfields FloatingLiteralBits; UnaryExprOrTypeTraitExprBitfields UnaryExprOrTypeTraitExprBits; + ArraySubscriptExprBitfields ArraySubscriptExprBits; DeclRefExprBitfields DeclRefExprBits; UnaryOperatorBitfields UnaryOperatorBits; CallExprBitfields CallExprBits; Index: lib/AST/Expr.cpp =================================================================== --- lib/AST/Expr.cpp +++ lib/AST/Expr.cpp @@ -1225,23 +1225,26 @@ ExprValueKind VK, SourceLocation rparenloc) : Expr(SC, t, VK, OK_Ordinary, fn->isTypeDependent(), fn->isValueDependent(), fn->isInstantiationDependent(), - fn->containsUnexpandedParameterPack()), - NumArgs(args.size()) { + fn->containsUnexpandedParameterPack()) { + unsigned NumArgs = args.size(); + CallExprBits.NumArgs = NumArgs; + assert((getNumArgs() == NumArgs) && "NumArgs overflow!"); unsigned NumPreArgs = preargs.size(); - SubExprs = new (C) Stmt *[args.size()+PREARGS_START+NumPreArgs]; + CallExprBits.NumPreArgs = NumPreArgs; + + SubExprs = new (C) Stmt *[NumArgs+PREARGS_START+NumPreArgs]; SubExprs[FN] = fn; for (unsigned i = 0; i != NumPreArgs; ++i) { updateDependenciesFromArg(preargs[i]); SubExprs[i+PREARGS_START] = preargs[i]; } - for (unsigned i = 0; i != args.size(); ++i) { + for (unsigned i = 0; i != NumArgs; ++i) { updateDependenciesFromArg(args[i]); SubExprs[i+PREARGS_START+NumPreArgs] = args[i]; } - CallExprBits.NumPreArgs = NumPreArgs; - RParenLoc = rparenloc; + setRParenLoc(rparenloc); } CallExpr::CallExpr(const ASTContext &C, StmtClass SC, Expr *fn, @@ -1259,7 +1262,8 @@ CallExpr::CallExpr(const ASTContext &C, StmtClass SC, unsigned NumPreArgs, EmptyShell Empty) - : Expr(SC, Empty), SubExprs(nullptr), NumArgs(0) { + : Expr(SC, Empty), SubExprs(nullptr) { + CallExprBits.NumArgs = 0; // FIXME: Why do we allocate this? SubExprs = new (C) Stmt*[PREARGS_START+NumPreArgs](); CallExprBits.NumPreArgs = NumPreArgs; @@ -1317,7 +1321,7 @@ // If shrinking # arguments, just delete the extras and forgot them. if (NumArgs < getNumArgs()) { - this->NumArgs = NumArgs; + CallExprBits.NumArgs = NumArgs; return; } @@ -1334,7 +1338,7 @@ if (SubExprs) C.Deallocate(SubExprs); SubExprs = NewSubExprs; - this->NumArgs = NumArgs; + CallExprBits.NumArgs = NumArgs; } /// getBuiltinCallee - If this is a call to a builtin, return the builtin ID. If Index: lib/Serialization/ASTReaderStmt.cpp =================================================================== --- lib/Serialization/ASTReaderStmt.cpp +++ lib/Serialization/ASTReaderStmt.cpp @@ -725,6 +725,7 @@ VisitExpr(E); E->setLHS(Record.readSubExpr()); E->setRHS(Record.readSubExpr()); + E->setLhsIsBase(Record.readInt()); E->setRBracketLoc(ReadSourceLocation()); } Index: lib/Serialization/ASTWriterStmt.cpp =================================================================== --- lib/Serialization/ASTWriterStmt.cpp +++ lib/Serialization/ASTWriterStmt.cpp @@ -638,6 +638,7 @@ VisitExpr(E); Record.AddStmt(E->getLHS()); Record.AddStmt(E->getRHS()); + Record.push_back(E->lhsIsBase()); Record.AddSourceLocation(E->getRBracketLoc()); Code = serialization::EXPR_ARRAY_SUBSCRIPT; }