aboutsummaryrefslogtreecommitdiff
path: root/lib/AST/ExprConstant.cpp
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2011-10-31 05:11:32 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2011-10-31 05:11:32 +0000
commit9e36b533af1b2fa9f32c4372c4081abdd86f47e0 (patch)
tree41173fe4be416b1432d9c8cce82d935f68f0ffdf /lib/AST/ExprConstant.cpp
parentba5d10b82b3cc00b4d71b273a18c051a1f38f22f (diff)
C++11 generalized constant expressions: evaluate equality comparisons between
arbitrary pointers, if those pointers don't point to weak objects or literals. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@143334 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/AST/ExprConstant.cpp')
-rw-r--r--lib/AST/ExprConstant.cpp80
1 files changed, 44 insertions, 36 deletions
diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp
index ee89529176..f4c9a8336c 100644
--- a/lib/AST/ExprConstant.cpp
+++ b/lib/AST/ExprConstant.cpp
@@ -257,6 +257,39 @@ static bool CheckConstantExpression(const CCValue &Value) {
return !Value.isLValue() || IsGlobalLValue(Value.getLValueBase());
}
+const ValueDecl *GetLValueBaseDecl(const LValue &LVal) {
+ if (!LVal.Base)
+ return 0;
+
+ if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(LVal.Base))
+ return DRE->getDecl();
+
+ // FIXME: Static data members accessed via a MemberExpr are represented as
+ // that MemberExpr. We should use the Decl directly instead.
+ if (const MemberExpr *ME = dyn_cast<MemberExpr>(LVal.Base)) {
+ assert(!isa<FieldDecl>(ME->getMemberDecl()) && "shouldn't see fields here");
+ return ME->getMemberDecl();
+ }
+
+ return 0;
+}
+
+static bool IsLiteralLValue(const LValue &Value) {
+ return Value.Base &&
+ !isa<DeclRefExpr>(Value.Base) &&
+ !isa<MemberExpr>(Value.Base);
+}
+
+static bool IsWeakLValue(const LValue &Value) {
+ const ValueDecl *Decl = GetLValueBaseDecl(Value);
+ if (!Decl)
+ return false;
+
+ return Decl->hasAttr<WeakAttr>() ||
+ Decl->hasAttr<WeakRefAttr>() ||
+ Decl->isWeakImported();
+}
+
static bool EvalPointerValueAsBool(const LValue &Value, bool &Result) {
const Expr* Base = Value.Base;
@@ -275,19 +308,7 @@ static bool EvalPointerValueAsBool(const LValue &Value, bool &Result) {
// be true, but if it'a decl-ref to a weak symbol it can be null at
// runtime.
Result = true;
-
- const DeclRefExpr* DeclRef = dyn_cast<DeclRefExpr>(Base);
- if (!DeclRef)
- return true;
-
- // If it's a weak symbol, it isn't constant-evaluable.
- const ValueDecl* Decl = DeclRef->getDecl();
- if (Decl->hasAttr<WeakAttr>() ||
- Decl->hasAttr<WeakRefAttr>() ||
- Decl->isWeakImported())
- return false;
-
- return true;
+ return !IsWeakLValue(Value);
}
static bool HandleConversionToBool(const CCValue &Val, bool &Result) {
@@ -417,23 +438,6 @@ static bool IsConstNonVolatile(QualType T) {
return Quals.hasConst() && !Quals.hasVolatile();
}
-const ValueDecl *GetLValueBaseDecl(const LValue &LVal) {
- if (!LVal.Base)
- return 0;
-
- if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(LVal.Base))
- return DRE->getDecl();
-
- // FIXME: Static data members accessed via a MemberExpr are represented as
- // that MemberExpr. We should use the Decl directly instead.
- if (const MemberExpr *ME = dyn_cast<MemberExpr>(LVal.Base)) {
- assert(!isa<FieldDecl>(ME->getMemberDecl()) && "shouldn't see fields here");
- return ME->getMemberDecl();
- }
-
- return 0;
-}
-
bool HandleLValueToRValueConversion(EvalInfo &Info, QualType Type,
const LValue &LVal, CCValue &RVal) {
const Expr *Base = LVal.Base;
@@ -1925,16 +1929,20 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
// Reject differing bases from the normal codepath; we special-case
// comparisons to null.
if (!HasSameBase(LHSValue, RHSValue)) {
+ // Inequalities and subtractions between unrelated pointers have
+ // unspecified or undefined behavior.
if (!E->isEqualityOp())
return false;
- if ((LHSValue.getLValueBase() || !LHSValue.getLValueOffset().isZero())&&
- (RHSValue.getLValueBase() || !RHSValue.getLValueOffset().isZero()))
+ // It's implementation-defined whether distinct literals will have
+ // distinct addresses. We define it to be unspecified.
+ if (IsLiteralLValue(LHSValue) || IsLiteralLValue(RHSValue))
return false;
- LValue &NonNull = LHSValue.getLValueBase() ? LHSValue : RHSValue;
- bool bres;
- if (!EvalPointerValueAsBool(NonNull, bres))
+ // We can't tell whether weak symbols will end up pointing to the same
+ // object.
+ if (IsWeakLValue(LHSValue) || IsWeakLValue(RHSValue))
return false;
- return Success(bres ^ (E->getOpcode() == BO_EQ), E);
+ // Pointers with different bases cannot represent the same object.
+ return Success(E->getOpcode() == BO_NE, E);
}
if (E->getOpcode() == BO_Sub) {