diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2014-10-21 23:01:04 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2014-10-21 23:01:04 +0000 |
commit | d20f1e6dd3153e2cda30addf79fb9f781a3449aa (patch) | |
tree | b1f7cfba70b80a77bf894519ee9e408afb70cd6b /clang/lib/AST/ExprConstant.cpp | |
parent | 7c93690be029a86d98cdad59ec4cb858c47e284f (diff) | |
download | bcm5719-llvm-d20f1e6dd3153e2cda30addf79fb9f781a3449aa.tar.gz bcm5719-llvm-d20f1e6dd3153e2cda30addf79fb9f781a3449aa.zip |
PR21327 / C++ DR1652 / C++ DR73: comparing a past-the-end pointer for one
complete object to a pointer to the start of another complete object does
not evaluate to the constant 'false'. All other comparisons between the
addresses of subobjects of distinct complete objects still do.
llvm-svn: 220343
Diffstat (limited to 'clang/lib/AST/ExprConstant.cpp')
-rw-r--r-- | clang/lib/AST/ExprConstant.cpp | 28 |
1 files changed, 28 insertions, 0 deletions
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 532720666bc..78de2578bee 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -6461,6 +6461,27 @@ static bool HasSameBase(const LValue &A, const LValue &B) { A.getLValueCallIndex() == B.getLValueCallIndex(); } +/// \brief Determine whether this is a pointer past the end of the complete +/// object referred to by the lvalue. +static bool isOnePastTheEndOfCompleteObject(const ASTContext &Ctx, + const LValue &LV) { + // A null pointer can be viewed as being "past the end" but we don't + // choose to look at it that way here. + if (!LV.getLValueBase()) + return false; + + // If the designator is valid and refers to a subobject, we're not pointing + // past the end. + if (!LV.getLValueDesignator().Invalid && + !LV.getLValueDesignator().isOnePastTheEnd()) + return false; + + // We're a past-the-end pointer if we point to the byte after the object, + // no matter what our type or path is. + auto Size = Ctx.getTypeSizeInChars(getType(LV.getLValueBase())); + return LV.getLValueOffset() == Size; +} + namespace { /// \brief Data recursive integer evaluator of certain binary operators. @@ -6923,6 +6944,13 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { // object. if (IsWeakLValue(LHSValue) || IsWeakLValue(RHSValue)) return Error(E); + // We can't compare the address of the start of one object with the + // past-the-end address of another object, per C++ DR1652. + if ((LHSValue.Base && LHSValue.Offset.isZero() && + isOnePastTheEndOfCompleteObject(Info.Ctx, RHSValue)) || + (RHSValue.Base && RHSValue.Offset.isZero() && + isOnePastTheEndOfCompleteObject(Info.Ctx, LHSValue))) + return Error(E); // Pointers with different bases cannot represent the same object. // (Note that clang defaults to -fmerge-all-constants, which can // lead to inconsistent results for comparisons involving the address |