Fix 20334: ImportC: enums created from string literal #defines don’t implicitly convert to const(char)* in D. (#21193)

Fixes: https://github.com/dlang/dmd/issues/20334

After preprocessing, #defines in C code that are just string literals
are converted into D enums. As these are collected for use in D code,
they should behave like D string literals and not C string literals.
This commit is contained in:
drpriver 2025-04-10 14:08:10 -07:00 committed by GitHub
parent 81cd0b26ef
commit e9984553e6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 31 additions and 7 deletions

View file

@ -4954,6 +4954,8 @@ struct ASTBase
/// If the string is parsed from a hex string literal /// If the string is parsed from a hex string literal
bool hexString = false; bool hexString = false;
/// If the string is from a collected C macro
bool cMacro = false;
extern (D) this(Loc loc, const(void)[] string) extern (D) this(Loc loc, const(void)[] string)
{ {
@ -4963,13 +4965,14 @@ struct ASTBase
this.sz = 1; // work around LDC bug #1286 this.sz = 1; // work around LDC bug #1286
} }
extern (D) this(Loc loc, const(void)[] string, size_t len, ubyte sz, char postfix = 0) extern (D) this(Loc loc, const(void)[] string, size_t len, ubyte sz, char postfix = 0, bool cMacro=false)
{ {
super(loc, EXP.string_, __traits(classInstanceSize, StringExp)); super(loc, EXP.string_, __traits(classInstanceSize, StringExp));
this.string = cast(char*)string; this.string = cast(char*)string;
this.len = len; this.len = len;
this.postfix = postfix; this.postfix = postfix;
this.sz = 1; // work around LDC bug #1286 this.sz = 1; // work around LDC bug #1286
this.cMacro = cMacro;
} }
/********************************************** /**********************************************

View file

@ -6193,7 +6193,7 @@ final class CParser(AST) : Parser!AST
/* Declare manifest constant: /* Declare manifest constant:
* enum id = "string"; * enum id = "string";
*/ */
AST.Expression e = new AST.StringExp(scanloc, str[0 .. len], len, 1, postfix); AST.Expression e = new AST.StringExp(scanloc, str[0 .. len], len, 1, postfix, true);
auto v = new AST.VarDeclaration(scanloc, null, id, new AST.ExpInitializer(scanloc, e), STC.manifest); auto v = new AST.VarDeclaration(scanloc, null, id, new AST.ExpInitializer(scanloc, e), STC.manifest);
addSym(v); addSym(v);
++p; ++p;

View file

@ -1406,6 +1406,8 @@ extern (C++) final class StringExp : Expression
/// If the string is parsed from a hex string literal /// If the string is parsed from a hex string literal
bool hexString = false; bool hexString = false;
/// If the string is from a collected C macro
bool cMacro = false;
enum char NoPostfix = 0; enum char NoPostfix = 0;
@ -1417,13 +1419,14 @@ extern (C++) final class StringExp : Expression
this.sz = 1; // work around LDC bug #1286 this.sz = 1; // work around LDC bug #1286
} }
extern (D) this(Loc loc, const(void)[] string, size_t len, ubyte sz, char postfix = NoPostfix) scope extern (D) this(Loc loc, const(void)[] string, size_t len, ubyte sz, char postfix = NoPostfix, bool cMacro = false) scope
{ {
super(loc, EXP.string_); super(loc, EXP.string_);
this.string = cast(char*)string.ptr; // note that this.string should be const this.string = cast(char*)string.ptr; // note that this.string should be const
this.len = len; this.len = len;
this.sz = sz; this.sz = sz;
this.postfix = postfix; this.postfix = postfix;
this.cMacro = cMacro;
} }
static StringExp create(Loc loc, const(char)* s) static StringExp create(Loc loc, const(char)* s)

View file

@ -353,6 +353,7 @@ public:
unsigned char sz; // 1: char, 2: wchar, 4: dchar unsigned char sz; // 1: char, 2: wchar, 4: dchar
d_bool committed; // if type is committed d_bool committed; // if type is committed
d_bool hexString; // if string is parsed from a hex string literal d_bool hexString; // if string is parsed from a hex string literal
d_bool cMacro; // If the string is from a collected C macro
static StringExp *create(Loc loc, const char *s); static StringExp *create(Loc loc, const char *s);
static StringExp *create(Loc loc, const void *s, d_size_t len); static StringExp *create(Loc loc, const void *s, d_size_t len);

View file

@ -4429,7 +4429,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
} }
buffer.write4(0); buffer.write4(0);
e.setData(buffer.extractData(), newlen, 4); e.setData(buffer.extractData(), newlen, 4);
if (sc && sc.inCfile) if (!e.cMacro && sc && sc.inCfile)
e.type = Type.tuns32.sarrayOf(e.len + 1); e.type = Type.tuns32.sarrayOf(e.len + 1);
else else
e.type = Type.tdchar.immutableOf().arrayOf(); e.type = Type.tdchar.immutableOf().arrayOf();
@ -4454,7 +4454,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
} }
buffer.writeUTF16(0); buffer.writeUTF16(0);
e.setData(buffer.extractData(), newlen, 2); e.setData(buffer.extractData(), newlen, 2);
if (sc && sc.inCfile) if (!e.cMacro && sc && sc.inCfile)
e.type = Type.tuns16.sarrayOf(e.len + 1); e.type = Type.tuns16.sarrayOf(e.len + 1);
else else
e.type = Type.twchar.immutableOf().arrayOf(); e.type = Type.twchar.immutableOf().arrayOf();
@ -4466,7 +4466,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
goto default; goto default;
default: default:
if (sc && sc.inCfile) if (!e.cMacro && sc && sc.inCfile)
e.type = Type.tchar.sarrayOf(e.len + 1); e.type = Type.tchar.sarrayOf(e.len + 1);
else else
e.type = Type.tchar.immutableOf().arrayOf(); e.type = Type.tchar.immutableOf().arrayOf();

View file

@ -3608,6 +3608,7 @@ public:
uint8_t sz; uint8_t sz;
bool committed; bool committed;
bool hexString; bool hexString;
bool cMacro;
enum : char { NoPostfix = 0u }; enum : char { NoPostfix = 0u };
static StringExp* create(Loc loc, const char* s); static StringExp* create(Loc loc, const char* s);
@ -5548,7 +5549,7 @@ private:
char realexp[48LLU]; char realexp[48LLU];
char complexexp[64LLU]; char complexexp[64LLU];
char symoffexp[56LLU]; char symoffexp[56LLU];
char stringexp[43LLU]; char stringexp[44LLU];
char arrayliteralexp[40LLU]; char arrayliteralexp[40LLU];
char assocarrayliteralexp[48LLU]; char assocarrayliteralexp[48LLU];
char structliteralexp[64LLU]; char structliteralexp[64LLU];

View file

@ -0,0 +1,2 @@
// https://github.com/dlang/dmd/issues/20334
#define X "X"

View file

@ -0,0 +1,14 @@
// https://github.com/dlang/dmd/issues/20334
// EXTRA_FILES: imports/imp20344.c
import imports.imp20344;
string s = X;
const(char)* p = X;
void takes_string(string){ }
void takes_char_star(const(char)*){ }
void test20344(){
takes_string(X);
takes_char_star(X);
}