Bug 7161 – Passing string literal by ref changes its bounds forever
Status
RESOLVED
Resolution
DUPLICATE
Severity
major
Priority
P2
Component
dmd
Product
D
Version
D2
Platform
Other
OS
Windows
Creation time
2011-12-24T04:41:00Z
Last change time
2015-06-09T05:11:54Z
Keywords
wrong-code
Assigned to
nobody
Creator
verylonglogin.reg
Comments
Comment #0 by verylonglogin.reg — 2011-12-24T04:41:24Z
---
import std.stdio;
void f(ref string s) {
writeln(s);
if(s.length)
--s.length;
else
s = "def";
}
void g1() { f("abc"); }
void g2() { f("abc"); }
void main()
{
g1(); // prints "abc"
g2(); // prints "ab"
f("abc"); // prints "a"
f("abc"); // prints ""
f("abc"); // prints "def"
}
---
Comment #1 by verylonglogin.reg — 2011-12-24T04:54:03Z
Workaround:
wrap every passed string `f("abc")` like `f(s("abc"))` and `f("11", "22", "33")` like `f(s("11"), s!1("22"), s!2("33"))` where `s` is:
---
ref string s(size_t n = 0)(string s) {
static string ss;
ss = s;
return ss;
}
---
It does have an easy workaround but is very annoying.
Comment #2 by andrej.mitrovich — 2011-12-24T05:21:38Z
Comment #3 by andrej.mitrovich — 2011-12-24T05:27:20Z
Actually s_impl isn't needed, s() can have that implementation it just needs a set of empty parens:
ref string s()(string s)
{
static string ss;
ss = s;
return ss;
}
Comment #4 by verylonglogin.reg — 2011-12-24T06:03:56Z
And a better one (CTFE friendly, no need to specify param number):
---
private ref string wrap(string s) {
static struct GCString { string str; }
auto gcStr = new GCString();
gcStr.str = s;
return gcStr.str;
}
---
Yes, hello Java-like arrays!
Comment #5 by issues.dlang — 2011-12-24T13:11:00Z
This code shouldn't even be legal. A string literal isn't an lvalue and can't be passed by reference. It's bug that that compiles at all. This looks like a duplicate of bug# 4539.
Comment #6 by verylonglogin.reg — 2011-12-25T02:49:32Z
*** This issue has been marked as a duplicate of issue 4539 ***