зеркало из https://github.com/microsoft/clang-1.git
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
This commit is contained in:
Родитель
ba5d10b82b
Коммит
9e36b533af
|
@ -257,6 +257,39 @@ static bool CheckConstantExpression(const CCValue &Value) {
|
||||||
return !Value.isLValue() || IsGlobalLValue(Value.getLValueBase());
|
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) {
|
static bool EvalPointerValueAsBool(const LValue &Value, bool &Result) {
|
||||||
const Expr* Base = Value.Base;
|
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
|
// be true, but if it'a decl-ref to a weak symbol it can be null at
|
||||||
// runtime.
|
// runtime.
|
||||||
Result = true;
|
Result = true;
|
||||||
|
return !IsWeakLValue(Value);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool HandleConversionToBool(const CCValue &Val, bool &Result) {
|
static bool HandleConversionToBool(const CCValue &Val, bool &Result) {
|
||||||
|
@ -417,23 +438,6 @@ static bool IsConstNonVolatile(QualType T) {
|
||||||
return Quals.hasConst() && !Quals.hasVolatile();
|
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,
|
bool HandleLValueToRValueConversion(EvalInfo &Info, QualType Type,
|
||||||
const LValue &LVal, CCValue &RVal) {
|
const LValue &LVal, CCValue &RVal) {
|
||||||
const Expr *Base = LVal.Base;
|
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
|
// Reject differing bases from the normal codepath; we special-case
|
||||||
// comparisons to null.
|
// comparisons to null.
|
||||||
if (!HasSameBase(LHSValue, RHSValue)) {
|
if (!HasSameBase(LHSValue, RHSValue)) {
|
||||||
|
// Inequalities and subtractions between unrelated pointers have
|
||||||
|
// unspecified or undefined behavior.
|
||||||
if (!E->isEqualityOp())
|
if (!E->isEqualityOp())
|
||||||
return false;
|
return false;
|
||||||
if ((LHSValue.getLValueBase() || !LHSValue.getLValueOffset().isZero())&&
|
// It's implementation-defined whether distinct literals will have
|
||||||
(RHSValue.getLValueBase() || !RHSValue.getLValueOffset().isZero()))
|
// distinct addresses. We define it to be unspecified.
|
||||||
|
if (IsLiteralLValue(LHSValue) || IsLiteralLValue(RHSValue))
|
||||||
return false;
|
return false;
|
||||||
LValue &NonNull = LHSValue.getLValueBase() ? LHSValue : RHSValue;
|
// We can't tell whether weak symbols will end up pointing to the same
|
||||||
bool bres;
|
// object.
|
||||||
if (!EvalPointerValueAsBool(NonNull, bres))
|
if (IsWeakLValue(LHSValue) || IsWeakLValue(RHSValue))
|
||||||
return false;
|
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) {
|
if (E->getOpcode() == BO_Sub) {
|
||||||
|
|
|
@ -161,8 +161,8 @@ namespace FunctionPointers {
|
||||||
namespace PointerComparison {
|
namespace PointerComparison {
|
||||||
|
|
||||||
int x, y;
|
int x, y;
|
||||||
constexpr bool g1 = &x == &y; // expected-error {{must be initialized by a constant expression}}
|
constexpr bool g1 = &x == &y;
|
||||||
constexpr bool g2 = &x != &y; // expected-error {{must be initialized by a constant expression}}
|
constexpr bool g2 = &x != &y;
|
||||||
constexpr bool g3 = &x <= &y; // expected-error {{must be initialized by a constant expression}}
|
constexpr bool g3 = &x <= &y; // expected-error {{must be initialized by a constant expression}}
|
||||||
constexpr bool g4 = &x >= &y; // expected-error {{must be initialized by a constant expression}}
|
constexpr bool g4 = &x >= &y; // expected-error {{must be initialized by a constant expression}}
|
||||||
constexpr bool g5 = &x < &y; // expected-error {{must be initialized by a constant expression}}
|
constexpr bool g5 = &x < &y; // expected-error {{must be initialized by a constant expression}}
|
||||||
|
@ -190,8 +190,16 @@ constexpr bool n10 = &x >= 0; // expected-error {{must be initialized by a const
|
||||||
constexpr bool n11 = &x < 0; // expected-error {{must be initialized by a constant expression}}
|
constexpr bool n11 = &x < 0; // expected-error {{must be initialized by a constant expression}}
|
||||||
constexpr bool n12 = &x > 0; // expected-error {{must be initialized by a constant expression}}
|
constexpr bool n12 = &x > 0; // expected-error {{must be initialized by a constant expression}}
|
||||||
|
|
||||||
|
constexpr bool s1 = &x == &x;
|
||||||
|
constexpr bool s2 = &x != &x;
|
||||||
|
constexpr bool s3 = &x <= &x;
|
||||||
|
constexpr bool s4 = &x >= &x;
|
||||||
|
constexpr bool s5 = &x < &x;
|
||||||
|
constexpr bool s6 = &x > &x;
|
||||||
|
|
||||||
using check = int[m1 + (m2<<1) + (m3<<2) + (m4<<3) + (m5<<4) + (m6<<5) +
|
using check = int[m1 + (m2<<1) + (m3<<2) + (m4<<3) + (m5<<4) + (m6<<5) +
|
||||||
(n1<<6) + (n2<<7) + (n7<<8) + (n8<<9)];
|
(n1<<6) + (n2<<7) + (n7<<8) + (n8<<9) + (g1<<10) + (g2<<11) +
|
||||||
using check = int[2+4+16+128+512];
|
(s1<<12) + (s2<<13) + (s3<<14) + (s4<<15) + (s5<<16) + (s6<<17)];
|
||||||
|
using check = int[2+4+16+128+512+2048+4096+16384+32768];
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче