r220343 - PR21327 / C++ DR1652 / C++ DR73: comparing a past-the-end pointer for one
Richard Smith
richard-llvm at metafoo.co.uk
Tue Oct 21 16:01:06 PDT 2014
Author: rsmith
Date: Tue Oct 21 18:01:04 2014
New Revision: 220343
URL: http://llvm.org/viewvc/llvm-project?rev=220343&view=rev
Log:
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.
Modified:
cfe/trunk/lib/AST/ExprConstant.cpp
cfe/trunk/test/CXX/drs/dr0xx.cpp
cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp
Modified: cfe/trunk/lib/AST/ExprConstant.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprConstant.cpp?rev=220343&r1=220342&r2=220343&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ExprConstant.cpp (original)
+++ cfe/trunk/lib/AST/ExprConstant.cpp Tue Oct 21 18:01:04 2014
@@ -6461,6 +6461,27 @@ static bool HasSameBase(const LValue &A,
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::VisitBinaryOperat
// 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
Modified: cfe/trunk/test/CXX/drs/dr0xx.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/drs/dr0xx.cpp?rev=220343&r1=220342&r2=220343&view=diff
==============================================================================
--- cfe/trunk/test/CXX/drs/dr0xx.cpp (original)
+++ cfe/trunk/test/CXX/drs/dr0xx.cpp Tue Oct 21 18:01:04 2014
@@ -823,7 +823,7 @@ namespace dr70 { // dr70: yes
namespace dr73 { // dr73: no
// The resolution to dr73 is unworkable. Consider:
int a, b;
- static_assert(&a + 1 != &b, "");
+ static_assert(&a + 1 != &b, ""); // expected-error {{not an integral constant expression}}
}
#endif
Modified: cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp?rev=220343&r1=220342&r2=220343&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp (original)
+++ cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp Tue Oct 21 18:01:04 2014
@@ -1935,3 +1935,7 @@ namespace PR19010 {
};
void test() { constexpr Test t; }
}
+
+void PR21327(int a, int b) {
+ static_assert(&a + 1 != &b, ""); // expected-error {{constant expression}}
+}
More information about the cfe-commits
mailing list