From: Ted Kremenek Date: Mon, 20 Aug 2007 16:18:38 +0000 (+0000) Subject: Modified ArraySubscriptExpr to have accessors getLHS and getRHS in addition X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=2324512285caac0332bbbc6e4cab6245d2a370a1;p=clang Modified ArraySubscriptExpr to have accessors getLHS and getRHS in addition to getBase and getIdx. getBase and getIdx now return a "normalized" view of the expression (e.g., always "A[4]" instead of possibly "4[A]"). getLHS and getRHS return the expressions with syntactic fidelity to the original source code. Also modified client code of ArraySubscriptExpr, including the AST dumper and pretty printer, the return-stack value checker, and the LLVM code generator. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@41180 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/AST/StmtDumper.cpp b/AST/StmtDumper.cpp index 9f82b0e647..7b0d7945f0 100644 --- a/AST/StmtDumper.cpp +++ b/AST/StmtDumper.cpp @@ -374,9 +374,9 @@ void StmtDumper::VisitSizeOfAlignOfTypeExpr(SizeOfAlignOfTypeExpr *Node) { void StmtDumper::VisitArraySubscriptExpr(ArraySubscriptExpr *Node) { DumpExpr(Node); fprintf(F, "\n"); - DumpSubTree(Node->getBase()); + DumpSubTree(Node->getLHS()); fprintf(F, "\n"); - DumpSubTree(Node->getIdx()); + DumpSubTree(Node->getRHS()); fprintf(F, ")"); } diff --git a/AST/StmtPrinter.cpp b/AST/StmtPrinter.cpp index 40884ae5cf..67a6be8be6 100644 --- a/AST/StmtPrinter.cpp +++ b/AST/StmtPrinter.cpp @@ -417,9 +417,9 @@ void StmtPrinter::VisitSizeOfAlignOfTypeExpr(SizeOfAlignOfTypeExpr *Node) { OS << Node->getArgumentType().getAsString() << ")"; } void StmtPrinter::VisitArraySubscriptExpr(ArraySubscriptExpr *Node) { - PrintExpr(Node->getBase()); + PrintExpr(Node->getLHS()); OS << "["; - PrintExpr(Node->getIdx()); + PrintExpr(Node->getRHS()); OS << "]"; } diff --git a/CodeGen/CGExpr.cpp b/CodeGen/CGExpr.cpp index 896db31a1b..b0d34a3380 100644 --- a/CodeGen/CGExpr.cpp +++ b/CodeGen/CGExpr.cpp @@ -495,35 +495,24 @@ LValue CodeGenFunction::EmitPreDefinedLValue(const PreDefinedExpr *E) { } LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E) { - // The index must always be a pointer or integer, neither of which is an - // aggregate. Emit it. + // The index must always be an integer, which is not an aggregate. Emit it. llvm::Value *Idx = EmitExpr(E->getIdx()).getVal(); // If the base is a vector type, then we are forming a vector element lvalue // with this subscript. - if (E->getBase()->getType()->isVectorType()) { + if (E->getLHS()->getType()->isVectorType()) { // Emit the vector as an lvalue to get its address. - LValue Base = EmitLValue(E->getBase()); - assert(Base.isSimple() && "Can only subscript lvalue vectors here!"); + LValue LHS = EmitLValue(E->getLHS()); + assert(LHS.isSimple() && "Can only subscript lvalue vectors here!"); // FIXME: This should properly sign/zero/extend or truncate Idx to i32. - return LValue::MakeVectorElt(Base.getAddress(), Idx); + return LValue::MakeVectorElt(LHS.getAddress(), Idx); } - // At this point, the base must be a pointer or integer, neither of which are - // aggregates. Emit it. + // The base must be a pointer, which is not an aggregate. Emit it. llvm::Value *Base = EmitExpr(E->getBase()).getVal(); - // Usually the base is the pointer type, but sometimes it is the index. - // Canonicalize to have the pointer as the base. - QualType BaseTy = E->getBase()->getType(); + // Extend or truncate the index type to 32 or 64-bits. QualType IdxTy = E->getIdx()->getType(); - if (isa(Idx->getType())) { - std::swap(Base, Idx); - std::swap(BaseTy, IdxTy); - } - - // The pointer is now the base. Extend or truncate the index type to 32 or - // 64-bits. bool IdxSigned = IdxTy->isSignedIntegerType(); unsigned IdxBitwidth = cast(Idx->getType())->getBitWidth(); if (IdxBitwidth != LLVMPointerWidth) diff --git a/Sema/SemaChecking.cpp b/Sema/SemaChecking.cpp index d699e1bcf8..a1deb3d256 100644 --- a/Sema/SemaChecking.cpp +++ b/Sema/SemaChecking.cpp @@ -16,6 +16,7 @@ #include "clang/AST/ASTContext.h" #include "clang/AST/Decl.h" #include "clang/AST/Expr.h" +#include "clang/AST/ExprCXX.h" #include "clang/Lex/Preprocessor.h" #include "clang/Lex/LiteralSupport.h" #include "clang/Basic/SourceManager.h" @@ -499,9 +500,24 @@ static DeclRefExpr* EvalAddr(Expr *E) { return NULL; } - // TODO: C++ casts. - case Stmt::CXXCastExprClass: - return NULL; + // C++ casts. For dynamic casts, static casts, and const casts, we + // are always converting from a pointer-to-pointer, so we just blow + // through the cast. In the case the dynamic cast doesn't fail + // (and return NULL), we take the conservative route and report cases + // where we return the address of a stack variable. For Reinterpre + case Stmt::CXXCastExprClass: { + CXXCastExpr *C = cast(E); + + if (C->getOpcode() == CXXCastExpr::ReinterpretCast) { + Expr *S = C->getSubExpr(); + if (S->getType()->isPointerType()) + return EvalAddr(S); + else + return NULL; + } + else + return EvalAddr(C->getSubExpr()); + } // Everything else: we simply don't reason about them. default: @@ -554,18 +570,7 @@ static DeclRefExpr* EvalVal(Expr *E) { // Array subscripts are potential references to data on the stack. We // retrieve the DeclRefExpr* for the array variable if it indeed // has local storage. - ArraySubscriptExpr *A = cast(E); - - // The array access could be written A[4] or 4[A] (both are equivalent). - // In the second case, the "base" is the offset and the "Idx" is - // the base. We test for this case by seeing if the Base expression - // has a pointer type. - Expr* Base = A->getBase(); - - if (Base->getType()->isPointerType()) - return EvalAddr(Base); - else - return EvalAddr(A->getIdx()); + return EvalAddr(cast(E)->getBase()); } case Stmt::ConditionalOperatorClass: { diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h index a5aba76d75..4314ceb6af 100644 --- a/include/clang/AST/Expr.h +++ b/include/clang/AST/Expr.h @@ -367,26 +367,38 @@ public: /// ArraySubscriptExpr - [C99 6.5.2.1] Array Subscripting. class ArraySubscriptExpr : public Expr { - Expr *Base, *Idx; + Expr *LHS, *RHS; SourceLocation RBracketLoc; public: - ArraySubscriptExpr(Expr *base, Expr *idx, QualType t, + ArraySubscriptExpr(Expr *lhs, Expr *rhs, QualType t, SourceLocation rbracketloc) : Expr(ArraySubscriptExprClass, t), - Base(base), Idx(idx), RBracketLoc(rbracketloc) {} + LHS(lhs), RHS(rhs), RBracketLoc(rbracketloc) {} - // NOTE: An array access can be written A[4] or 4[A] (both are equivalent). - // In the second case, getBase() actually returns the index and getIdx() - // returns the offset. Only one of the subexpressions will have a pointer - // type (the base), so the second case can be identified using the - // expression getBase()->getType()->isPointerType(). - Expr *getBase() { return Base; } - const Expr *getBase() const { return Base; } - Expr *getIdx() { return Idx; } - const Expr *getIdx() const { return Idx; } + /// An array access can be written A[4] or 4[A] (both are equivalent). + /// - getBase() and getIdx() always present the normalized view: A[4]. + /// In this case getBase() returns "A" and getIdx() returns "4". + /// - getLHS() and getRHS() present the syntactic view. e.g. for + /// 4[A] getLHS() returns "4". + + Expr *getBase() { return (LHS->getType()->isIntegerType()) ? RHS : LHS; } + const Expr *getBase() const { + return (LHS->getType()->isIntegerType()) ? RHS : LHS; + } + + Expr *getIdx() { return (LHS->getType()->isIntegerType()) ? LHS : RHS; } + const Expr *getIdx() const { + return (LHS->getType()->isIntegerType()) ? LHS : RHS; + } + + Expr *getLHS() { return LHS; } + const Expr *getLHS() const { return LHS; } + + Expr *getRHS() { return RHS; } + const Expr *getRHS() const { return RHS; } SourceRange getSourceRange() const { - return SourceRange(Base->getLocStart(), RBracketLoc); + return SourceRange(LHS->getLocStart(), RBracketLoc); } virtual SourceLocation getExprLoc() const { return RBracketLoc; }