This code fails to compile with DMD 2.064 beta:
class OS
{
static const char[] REBARCLASSNAME = "ReBarWindow32";
}
class CoolBar
{
static const char* ReBarClass = OS.REBARCLASSNAME.ptr; // line 14
}
Error message:
main.d(14): Error: cannot use non-constant CTFE pointer in an initializer '"ReBarWindow32"[0]'
The commit that caused this regression is:
43a6c87194cae799650249b10a4f7c910081d280
Comment #1 by clugdbug — 2013-10-16T07:08:18Z
Did this actually work correctly before?
Or was it acting as macro, ie was equivalent to:
static const char* ReBarClass = "ReBarWindow32".ptr;
?
Tests that I've done suggest that it was acting as a macro.
Obviously this should work. But is it actually a regression, or a change from wrong-code --> rejects-valid ?
In any case it is probably just an over-zealous check in init.c : hasNonConstPointers().
Comment #2 by doob — 2013-10-16T11:51:50Z
(In reply to comment #1)
> Did this actually work correctly before?
>
> Or was it acting as macro, ie was equivalent to:
> static const char* ReBarClass = "ReBarWindow32".ptr;
> ?
What do you mean "acting as a macro"?
> Tests that I've done suggest that it was acting as a macro.
> Obviously this should work. But is it actually a regression, or a change from
> wrong-code --> rejects-valid ?
I don't know. All I'm saying is that it used to compile but now it doesn't.
Comment #3 by clugdbug — 2013-10-16T18:46:18Z
This isn't a regression. It used to compile, but it generated wrong code.
Here's a reduced case:
---
static const char [] x = "abc";
static const char *p = x.ptr;
void main()
{
assert(p == x.ptr);
}
---
2.063: compiles, but assert fails
2.064: does not compile.
That's an improvement.
With the way the glue layer works at the moment, I don't think this can be made to work right now. The glue layer only allows you to have a pointer to a symbol, but this is a pointer to a nameless string literal. It could never have generated correct code.
Comment #4 by luis — 2013-10-16T20:54:58Z
(In reply to comment #3)
> This isn't a regression. It used to compile, but it generated wrong code.
This also used to compile and fail the assert:
const foo = "foo";
const(char)* p = foo.ptr;
void main()
{
assert(p == foo.ptr);
}
(although I did not rely on that behavior, so for me this was a regression)
But if you change to:
const foo = "foo";
const(char)* p = foo; // remove .ptr
void main()
{
assert(p == foo.ptr);
}
It still compiles with git head, and fails the assert.
Comment #5 by clugdbug — 2013-10-18T00:25:23Z
(In reply to comment #4)
> (In reply to comment #3)
> > This isn't a regression. It used to compile, but it generated wrong code.
>
> This also used to compile and fail the assert:
>
> const foo = "foo";
> const(char)* p = foo.ptr;
>
> void main()
> {
> assert(p == foo.ptr);
> }
>
> (although I did not rely on that behavior, so for me this was a regression)
The compiler was still generating wrong code.
I'm downgrading this bug from regression to rejects-valid, since AFAIK there were no cases where the compiler generated correct code.
Sometimes there are "regressions" where something no longer compiles that was previously wrong, but happened to work in a few special cases. But this doesn't even seem to be one of those issues. It was always wrong.
> But if you change to:
>
> const foo = "foo";
> const(char)* p = foo; // remove .ptr
>
> void main()
> {
> assert(p == foo.ptr);
> }
>
> It still compiles with git head, and fails the assert.
Interesting. I'm not sure if that's a bug, or not. It's a slightly different case though.
It's treating "foo" as a rvalue, not an lvalue. It evaluates foo, and the implicit conversion to char * happens afterwards. But with ".ptr" it _has_ to treat foo as an lvalue. while evaluating it. So the order of evaluation is different.
Comment #6 by doob — 2013-10-18T02:32:32Z
(In reply to comment #3)
> This isn't a regression. It used to compile, but it generated wrong code.
> Here's a reduced case:
> ---
> static const char [] x = "abc";
> static const char *p = x.ptr;
>
> void main()
> {
> assert(p == x.ptr);
> }
> ---
I think the original code only wanted a char* with the content "ReBarWindow32" at compile time.
Comment #7 by syniurge — 2016-01-11T02:22:06Z
Still there:
struct A {
uint d;
}
immutable A abc = { 42 };
immutable(uint)* xyz = &abc.d;
----
Error: cannot use non-constant CTFE pointer in an initializer '&A(42u).d'
I need to initialize a global variable with the address of a global struct variable member and the workaround to get past that error was to do it in a static ctor but that's not great since this is inside a template mixin meant to be used in tons of places.
Although I'm only interested in the address the CTFE interpreter always "resolves" abc into the literal.
Comment #8 by simen.kjaras — 2019-06-03T06:00:31Z
*** Issue 19935 has been marked as a duplicate of this issue. ***
Comment #9 by robert.schadek — 2024-12-13T18:12:53Z