More work on the constant evaluator. Eli, it would be great if you could have a look at this.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@59420 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp
index 0823683..4a67956 100644
--- a/lib/AST/ExprConstant.cpp
+++ b/lib/AST/ExprConstant.cpp
@@ -124,6 +124,7 @@
   APValue VisitCompoundLiteralExpr(CompoundLiteralExpr *E);
   APValue VisitMemberExpr(MemberExpr *E);
   APValue VisitStringLiteral(StringLiteral *E) { return APValue(E, 0); }
+  APValue VisitArraySubscriptExpr(ArraySubscriptExpr *E);
 };
 } // end anonymous namespace
 
@@ -169,6 +170,24 @@
   return result;
 }
 
+APValue LValueExprEvaluator::VisitArraySubscriptExpr(ArraySubscriptExpr *E)
+{
+  APValue Result;
+  
+  if (!EvaluatePointer(E->getBase(), Result, Info))
+    return APValue();
+  
+  APSInt Index;
+  if (!EvaluateInteger(E->getIdx(), Index, Info))
+    return APValue();
+
+  uint64_t ElementSize = Info.Ctx.getTypeSize(E->getType()) / 8;
+
+  uint64_t Offset = Index.getSExtValue() * ElementSize;
+  Result.setLValue(Result.getLValueBase(), 
+                   Result.getLValueOffset() + Offset);
+  return Result;
+}
 
 //===----------------------------------------------------------------------===//
 // Pointer Evaluation
@@ -384,6 +403,18 @@
   }
   bool VisitSizeOfAlignOfExpr(const SizeOfAlignOfExpr *E);
 
+  bool VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *E) {
+    Result = E->getValue();
+    Result.setIsUnsigned(E->getType()->isUnsignedIntegerType());
+    return true;
+  }
+  
+  bool VisitCXXZeroInitValueExpr(const CXXZeroInitValueExpr *E) {
+    Result = APSInt::getNullValue(getIntTypeSizeInBits(E->getType()));
+    Result.setIsUnsigned(E->getType()->isUnsignedIntegerType());
+    return true;
+  }
+
 private:
   bool HandleCast(SourceLocation CastLoc, Expr *SubExpr, QualType DestType);
 };
@@ -572,6 +603,40 @@
     return true;
   }
   
+  if (E->getOpcode() == BinaryOperator::Sub) {
+    if (LHSTy->isPointerType()) {
+      if (RHSTy->isIntegralType()) {
+        // pointer - int.
+        // FIXME: Implement.
+      }
+      
+      assert(RHSTy->isPointerType() && "RHS not pointer!");
+
+      APValue LHSValue;
+      if (!EvaluatePointer(E->getLHS(), LHSValue, Info))
+        return false;
+      
+      APValue RHSValue;
+      if (!EvaluatePointer(E->getRHS(), RHSValue, Info))
+        return false;
+      
+      // FIXME: Is this correct? What if only one of the operands has a base?
+      if (LHSValue.getLValueBase() || RHSValue.getLValueBase())
+        return false;
+      
+      const QualType Type = E->getLHS()->getType();
+      const QualType ElementType = Type->getAsPointerType()->getPointeeType();
+
+      uint64_t D = LHSValue.getLValueOffset() - RHSValue.getLValueOffset();
+      D /= Info.Ctx.getTypeSize(ElementType) / 8;
+      
+      Result = D;
+      Result.zextOrTrunc(getIntTypeSizeInBits(E->getType()));
+      Result.setIsUnsigned(E->getType()->isUnsignedIntegerType());
+    
+      return true;
+    }
+  }
   if (!LHSTy->isIntegralType() ||
       !RHSTy->isIntegralType()) {
     // We can't continue from here for non-integral types, and they
@@ -586,7 +651,6 @@
     return false; // error in subexpression.
   }
 
-  // FIXME: Handle pointer subtraction
 
   // FIXME Maybe we want to succeed even where we can't evaluate the
   // right side of LAnd/LOr?