summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorEli Friedman <eli.friedman@gmail.com>2012-04-16 04:30:08 +0000
committerEli Friedman <eli.friedman@gmail.com>2012-04-16 04:30:08 +0000
commita31698842e9893559d58a7bf1a987f2ae90bea0b (patch)
tree922756511b8ac29e37c3934fc6bdf5c1199159fc /lib
parent4762a2da74875d2ae94e0d77d38ed964816cce36 (diff)
Make constant evaluation for pointer comparisons work correctly for some uncommon cases. <rdar://problem/10962435>.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@154794 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r--lib/AST/ExprConstant.cpp24
1 files changed, 18 insertions, 6 deletions
diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp
index 4a06e74615..4839c29976 100644
--- a/lib/AST/ExprConstant.cpp
+++ b/lib/AST/ExprConstant.cpp
@@ -5088,14 +5088,26 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
}
}
+ // The comparison here must be unsigned, and performed with the same
+ // width as the pointer.
+ // FIXME: Knowing the base is the same for the LHS and RHS isn't enough
+ // for relational operators.
+ unsigned PtrSize = Info.Ctx.getTypeSize(LHSTy);
+ uint64_t CompareLHS = LHSOffset.getQuantity();
+ uint64_t CompareRHS = RHSOffset.getQuantity();
+ assert(PtrSize <= 64 && "Unexpected pointer width");
+ uint64_t Mask = ~0ULL >> (64 - PtrSize);
+ CompareLHS &= Mask;
+ CompareRHS &= Mask;
+
switch (E->getOpcode()) {
default: llvm_unreachable("missing comparison operator");
- case BO_LT: return Success(LHSOffset < RHSOffset, E);
- case BO_GT: return Success(LHSOffset > RHSOffset, E);
- case BO_LE: return Success(LHSOffset <= RHSOffset, E);
- case BO_GE: return Success(LHSOffset >= RHSOffset, E);
- case BO_EQ: return Success(LHSOffset == RHSOffset, E);
- case BO_NE: return Success(LHSOffset != RHSOffset, E);
+ case BO_LT: return Success(CompareLHS < CompareRHS, E);
+ case BO_GT: return Success(CompareLHS > CompareRHS, E);
+ case BO_LE: return Success(CompareLHS <= CompareRHS, E);
+ case BO_GE: return Success(CompareLHS >= CompareRHS, E);
+ case BO_EQ: return Success(CompareLHS == CompareRHS, E);
+ case BO_NE: return Success(CompareLHS != CompareRHS, E);
}
}
}