diff options
author | Eli Friedman <eli.friedman@gmail.com> | 2009-03-24 01:14:50 +0000 |
---|---|---|
committer | Eli Friedman <eli.friedman@gmail.com> | 2009-03-24 01:14:50 +0000 |
commit | 94c25c66b5ed45f579953e5efaaa4a11ac47d847 (patch) | |
tree | b625ddfa03cc2a1519dc426adac56052300dde3b | |
parent | 703a77f31346d1d3ee98cd6bfa527f7cac1934c3 (diff) | |
download | bcm5719-llvm-94c25c66b5ed45f579953e5efaaa4a11ac47d847.tar.gz bcm5719-llvm-94c25c66b5ed45f579953e5efaaa4a11ac47d847.zip |
Fix PR3868 by making Evaluate handle cases like "(long)&a + 4".
llvm-svn: 67593
-rw-r--r-- | clang/lib/AST/ExprConstant.cpp | 33 | ||||
-rw-r--r-- | clang/test/Sema/init.c | 3 |
2 files changed, 30 insertions, 6 deletions
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index c2449166fc6..b0954e149c4 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -918,7 +918,6 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { !RHSTy->isIntegralType()) { // We can't continue from here for non-integral types, and they // could potentially confuse the following operations. - // FIXME: Deal with EQ and friends. return false; } @@ -926,14 +925,36 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { if (!Visit(E->getLHS())) return false; // error in subexpression. - // Only support arithmetic on integers for now. - if (!Result.isInt()) + APValue RHSVal; + if (!EvaluateIntegerOrLValue(E->getRHS(), RHSVal, Info)) return false; - - llvm::APSInt RHS; - if (!EvaluateInteger(E->getRHS(), RHS, Info)) + + // Handle cases like (unsigned long)&a + 4. + if (E->isAdditiveOp() && Result.isLValue() && RHSVal.isInt()) { + uint64_t offset = Result.getLValueOffset(); + if (E->getOpcode() == BinaryOperator::Add) + offset += RHSVal.getInt().getZExtValue(); + else + offset -= RHSVal.getInt().getZExtValue(); + Result = APValue(Result.getLValueBase(), offset); + return true; + } + + // Handle cases like 4 + (unsigned long)&a + if (E->getOpcode() == BinaryOperator::Add && + RHSVal.isLValue() && Result.isInt()) { + uint64_t offset = RHSVal.getLValueOffset(); + offset += Result.getInt().getZExtValue(); + Result = APValue(RHSVal.getLValueBase(), offset); + return true; + } + + // All the following cases expect both operands to be an integer + if (!Result.isInt() || !RHSVal.isInt()) return false; + APSInt& RHS = RHSVal.getInt(); + switch (E->getOpcode()) { default: return Error(E->getOperatorLoc(), diag::note_invalid_subexpr_in_ice, E); diff --git a/clang/test/Sema/init.c b/clang/test/Sema/init.c index 6f592b80e60..73c6887889b 100644 --- a/clang/test/Sema/init.c +++ b/clang/test/Sema/init.c @@ -120,3 +120,6 @@ ivector4 vtest2 = __builtin_choose_expr(1, (ivector4){1}, (ivector4){1}); ivector4 vtest3 = __real__ (ivector4){1}; ivector4 vtest4 = __imag__ (ivector4){1}; +uintptr_t ptrasintadd1 = (uintptr_t)&a - 4; +uintptr_t ptrasintadd2 = (uintptr_t)&a + 4; +uintptr_t ptrasintadd3 = 4 + (uintptr_t)&a; |