diff --git a/changelog/dmd.string-postfix-ptr.dd b/changelog/dmd.string-postfix-ptr.dd new file mode 100644 index 000000000000..92e3d72449be --- /dev/null +++ b/changelog/dmd.string-postfix-ptr.dd @@ -0,0 +1,19 @@ +String literals with a postfix can now implicitly convert to a `const` pointer + +A string literal with a `StringPostfix` (`c`, `w`, or `d`) can now implicitly +convert to a `const` or `immutable` pointer of the corresponding character type, +consistent with how unpostfixed string literals behave: + +------- +const(char)* p1 = "hello"c; +const(wchar)* p2 = "hello"w; +const(dchar)* p3 = "hello"d; +------- + +This makes it easier to pass a string literal with an explicit wide character type to a C API. + +---- +GetModuleHandleW("opengl32.dll"); // already possible +GetModuleHandle("opengl32.dll"w.ptr); // already possible +GetModuleHandle("opengl32.dll"w); // now also allowed +--- diff --git a/compiler/src/dmd/dcast.d b/compiler/src/dmd/dcast.d index 1d1de8dd5ee1..dea540c98619 100644 --- a/compiler/src/dmd/dcast.d +++ b/compiler/src/dmd/dcast.d @@ -823,6 +823,8 @@ MATCH implicitConvTo(Expression e, Type t) break; } } + else if (t.ty == Tpointer && e.type.isStaticOrDynamicArray() && e.type.nextOf().isImmutable() && tn.ty == tyn) + return m; // e.g. "foo"w -> const(wchar)* break; default: diff --git a/compiler/test/runnable/implicit.d b/compiler/test/runnable/implicit.d index 802e382c5253..9f14e9fdbb54 100644 --- a/compiler/test/runnable/implicit.d +++ b/compiler/test/runnable/implicit.d @@ -474,6 +474,19 @@ void test15778() static assert(!__traits(compiles, (ds[] = "a"w))); } +/***********************************/ +// https://github.com/dlang/dmd/issues/18342 +const(char)* cptr = "tic"c; +const(wchar)* wcptr = "tac"w; +immutable(dchar)* dcptr = "toe"d; + +void test18342() +{ + assert( cptr[0 .. 4] == "tic\0"c); + assert(wcptr[0 .. 4] == "tac\0"w); + assert(dcptr[0 .. 4] == "toe\0"d); +} + /***********************************/ void main() @@ -490,6 +503,7 @@ void main() testDIP29_5(); testDIP29_6(); test15778(); + test18342(); printf("Success\n"); } diff --git a/spec/expression.dd b/spec/expression.dd index 0a3030571f1a..032c7e434534 100644 --- a/spec/expression.dd +++ b/spec/expression.dd @@ -2215,6 +2215,19 @@ $(H3 $(LEGACY_LNAME2 StringLiteral, string_literals, String Literals)) $(TROW $(D immutable(dchar)[])) ) + $(P A string literal with a $(DDSUBLINK spec/lex, string_postfix, StringPostfix) + has a fixed character type and can implicitly convert to a + $(D const) or $(D immutable) pointer of that character type: + ) + + $(SPEC_RUNNABLE_EXAMPLE_COMPILE + ------------- + const(char)* p1 = "hello"c; + const(wchar)* p2 = "hello"w; + const(dchar)* p3 = "hello"d; + ------------- + ) + $(UNDEFINED_BEHAVIOR writing to a string literal. This is not allowed in `@safe` code.) $(P By default, a string literal is typed as a dynamic array, but the element