]> granicus.if.org Git - clang/commitdiff
Modified ArraySubscriptExpr to have accessors getLHS and getRHS in addition
authorTed Kremenek <kremenek@apple.com>
Mon, 20 Aug 2007 16:18:38 +0000 (16:18 +0000)
committerTed Kremenek <kremenek@apple.com>
Mon, 20 Aug 2007 16:18:38 +0000 (16:18 +0000)
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

AST/StmtDumper.cpp
AST/StmtPrinter.cpp
CodeGen/CGExpr.cpp
Sema/SemaChecking.cpp
include/clang/AST/Expr.h

index 9f82b0e64753bc9cbee6101d533e6cc410cc416f..7b0d7945f017f9b92a8480c905f7bd9187ba4f52 100644 (file)
@@ -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, ")");
 }
 
index 40884ae5cf3db013f49a40db754a9955f5b8a1fb..67a6be8be6eb5eb6e36fde0ba922359f8022f6ca 100644 (file)
@@ -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 << "]";
 }
 
index 896db31a1b9293323a5420ef2ffbacdf0eaaf3dc..b0d34a33807d76c12e6b6652b9ad050eddb480d6 100644 (file)
@@ -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)
index d699e1bcf818f0989cc46ee1317cea0dba93afe2..a1deb3d256dd485e6c03e6480903843a90e54c5e 100644 (file)
@@ -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: {
index a5aba76d7573b90bbbe2d225d9e1b9dd889b1b08..4314ceb6af4ff0698202816a1d2adbc9186dba76 100644 (file)
@@ -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; }