aboutsummaryrefslogtreecommitdiff
path: root/lib/AST/ExprConstant.cpp
diff options
context:
space:
mode:
authorEd Schouten <ed@FreeBSD.org>2009-06-14 09:24:02 +0000
committerEd Schouten <ed@FreeBSD.org>2009-06-14 09:24:02 +0000
commit7ef7bab7e3d06f660b059b903c231f100bb13cc5 (patch)
treed472a7615b5c7e413aa62a77d0777c1a9cf76478 /lib/AST/ExprConstant.cpp
parent8ba99c00327a4394e7568244d6cffd6e62625a7a (diff)
downloadsrc-7ef7bab7e3d06f660b059b903c231f100bb13cc5.tar.gz
src-7ef7bab7e3d06f660b059b903c231f100bb13cc5.zip
Import Clang r73340.vendor/clang/clang-r73340
Notes
Notes: svn path=/vendor/clang/dist/; revision=194179 svn path=/vendor/clang/clang-r73340/; revision=194181; tag=vendor/clang/clang-r73340
Diffstat (limited to 'lib/AST/ExprConstant.cpp')
-rw-r--r--lib/AST/ExprConstant.cpp38
1 files changed, 30 insertions, 8 deletions
diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp
index 8e3c3ce2d309..4815ae5c3b94 100644
--- a/lib/AST/ExprConstant.cpp
+++ b/lib/AST/ExprConstant.cpp
@@ -16,6 +16,7 @@
#include "clang/AST/RecordLayout.h"
#include "clang/AST/StmtVisitor.h"
#include "clang/AST/ASTDiagnostic.h"
+#include "clang/Basic/Builtins.h"
#include "clang/Basic/TargetInfo.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/Compiler.h"
@@ -61,6 +62,13 @@ static bool EvaluateComplex(const Expr *E, APValue &Result, EvalInfo &Info);
// Misc utilities
//===----------------------------------------------------------------------===//
+static bool EvalPointerValueAsBool(APValue& Value, bool& Result) {
+ // FIXME: Is this accurate for all kinds of bases? If not, what would
+ // the check look like?
+ Result = Value.getLValueBase() || Value.getLValueOffset();
+ return true;
+}
+
static bool HandleConversionToBool(Expr* E, bool& Result, EvalInfo &Info) {
if (E->getType()->isIntegralType()) {
APSInt IntResult;
@@ -78,10 +86,7 @@ static bool HandleConversionToBool(Expr* E, bool& Result, EvalInfo &Info) {
APValue PointerResult;
if (!EvaluatePointer(E, PointerResult, Info))
return false;
- // FIXME: Is this accurate for all kinds of bases? If not, what would
- // the check look like?
- Result = PointerResult.getLValueBase() || PointerResult.getLValueOffset();
- return true;
+ return EvalPointerValueAsBool(PointerResult, Result);
} else if (E->getType()->isAnyComplexType()) {
APValue ComplexResult;
if (!EvaluateComplex(E, ComplexResult, Info))
@@ -936,10 +941,27 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
if (!EvaluatePointer(E->getRHS(), RHSValue, Info))
return false;
- // Reject any bases; this is conservative, but good enough for
- // common uses
- if (LHSValue.getLValueBase() || RHSValue.getLValueBase())
- return false;
+ // Reject any bases from the normal codepath; we special-case comparisons
+ // to null.
+ if (LHSValue.getLValueBase()) {
+ if (!E->isEqualityOp())
+ return false;
+ if (RHSValue.getLValueBase() || RHSValue.getLValueOffset())
+ return false;
+ bool bres;
+ if (!EvalPointerValueAsBool(LHSValue, bres))
+ return false;
+ return Success(bres ^ (E->getOpcode() == BinaryOperator::EQ), E);
+ } else if (RHSValue.getLValueBase()) {
+ if (!E->isEqualityOp())
+ return false;
+ if (LHSValue.getLValueBase() || LHSValue.getLValueOffset())
+ return false;
+ bool bres;
+ if (!EvalPointerValueAsBool(RHSValue, bres))
+ return false;
+ return Success(bres ^ (E->getOpcode() == BinaryOperator::EQ), E);
+ }
if (E->getOpcode() == BinaryOperator::Sub) {
const QualType Type = E->getLHS()->getType();