www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - [Issue 8886] New: [CTFE] a check failure of memory block inclusion

reply d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=8886

           Summary: [CTFE] a check failure of memory block inclusion
           Product: D
           Version: D2
          Platform: All
        OS/Version: All
            Status: NEW
          Keywords: CTFE
          Severity: normal
          Priority: P2
         Component: DMD
        AssignedTo: nobody puremagic.com
        ReportedBy: k.hara.pg gmail.com



From the comment at https://github.com/D-Programming-Language/druntime/pull/335
---
version = bug;

bool foo(const(int)[] a, const(int)[] b)
{
  version(bug) {
    return a.length &&
           b.ptr >= a.ptr &&
           b.ptr + b.length <= a.ptr + a.length;
  } else {
    if (a.length && b.length)
    {
        auto bend = b.ptr + b.length;
        auto aend = a.ptr + a.length;
        return a.ptr <= b.ptr && bend <= aend;
    }
    return false;
  }
}
bool bug1()
{
    auto a1 = [1,2,3,4,5];
    return foo(a1[0..4], a1[2..4]);
}
bool bug2()
{
    auto a1 = [1,2,3,4,5];
    auto a2 = [1,2,3,4,5];
    return foo(a1[0..4], a2[2..4]);
}
static assert( bug1());
static assert(!bug2());    // Fails CTFE when version = bug; defines.
---

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Oct 24 2012
next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=8886


Don <clugdbug yahoo.com.au> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Keywords|                            |diagnostic
                 CC|                            |clugdbug yahoo.com.au



This behaviour is intentional. The relevant line is:

return a.length &&
       b.ptr >= a.ptr &&
       b.ptr + b.length <= a.ptr + a.length;

This means:
return (a.length &&
       b.ptr >= a.ptr) &&
       b.ptr + b.length <= a.ptr + a.length;

If the b.ptr < a.ptr, then the first subexpression fails, and because of
short-circuit evaluation, b.ptr + b.length <= a.ptr + a.length is never
evaluated.

What you actually want is:

return a.length &&
       (b.ptr >= a.ptr &&
       b.ptr + b.length <= a.ptr + a.length);

Now in this particular case, the compiler could recognize e1 && e2 && e3 but it
won't work in general, I think it makes things unpredictable.

Changing to a diagnostic bug.

I'm so disappointed, I went to a lot of trouble to give a good error message
(even using the variable names you used!), and it seems it's still not clear
enough. Any suggestions?

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Oct 24 2012
prev sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=8886




To clarify: When I say "it won't work in general", the problem is things like:

a < b && c < d && e > f

If a and b are pointers to the same memory block, then a < b is OK, and this
expression means:
a < b && isInside(c..e, d..f)
but if a and b are different pointers, then it would be:
isInside(a..c, b..d) && e > f
which is OK as long as e and f are in the same memory block.

then there is an explosion of possible cases, and many similar things _still_
aren't handled ( eg, a1 < b1 && c1 < d1 && a2 > b2 && c2 > d2, why isn't this
recognized as two isInside operations?)

So the rule is simple: they have to be part of a single && or || expression.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Oct 24 2012