Bug 8886 – [CTFE] a check failure of memory block inclusion

Status
NEW
Severity
normal
Priority
P3
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2012-10-24T09:29:15Z
Last change time
2024-12-13T18:01:58Z
Keywords
CTFE, diagnostic
Assigned to
No Owner
Creator
Kenji Hara
Moved to GitHub: dmd#17560 →

Comments

Comment #0 by k.hara.pg — 2012-10-24T09:29:15Z
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. ---
Comment #1 by clugdbug — 2012-10-24T10:42:30Z
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?
Comment #2 by clugdbug — 2012-10-24T10:57:37Z
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.
Comment #3 by robert.schadek — 2024-12-13T18:01:58Z
THIS ISSUE HAS BEEN MOVED TO GITHUB https://github.com/dlang/dmd/issues/17560 DO NOT COMMENT HERE ANYMORE, NOBODY WILL SEE IT, THIS ISSUE HAS BEEN MOVED TO GITHUB