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. llvm-svn: 41180
This commit is contained in:
parent
9c3d20d823
commit
c81614d5d1
|
|
@ -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, ")");
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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 << "]";
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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<llvm::PointerType>(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<llvm::IntegerType>(Idx->getType())->getBitWidth();
|
||||
if (IdxBitwidth != LLVMPointerWidth)
|
||||
|
|
|
|||
|
|
@ -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<CXXCastExpr>(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<ArraySubscriptExpr>(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<ArraySubscriptExpr>(E)->getBase());
|
||||
}
|
||||
|
||||
case Stmt::ConditionalOperatorClass: {
|
||||
|
|
|
|||
|
|
@ -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; }
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue