From e9984553e63a1ff3533bca258feaeb22b92f2bc3 Mon Sep 17 00:00:00 2001 From: drpriver Date: Thu, 10 Apr 2025 14:08:10 -0700 Subject: [PATCH] =?UTF-8?q?Fix=2020334:=20ImportC:=20enums=20created=20fro?= =?UTF-8?q?m=20string=20literal=20#defines=20don=E2=80=99t=20implicitly=20?= =?UTF-8?q?convert=20to=20const(char)*=20in=20D.=20(#21193)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. --- compiler/src/dmd/astbase.d | 5 ++++- compiler/src/dmd/cparse.d | 2 +- compiler/src/dmd/expression.d | 5 ++++- compiler/src/dmd/expression.h | 1 + compiler/src/dmd/expressionsem.d | 6 +++--- compiler/src/dmd/frontend.h | 3 ++- compiler/test/compilable/imports/imp20344.c | 2 ++ compiler/test/compilable/test20344.d | 14 ++++++++++++++ 8 files changed, 31 insertions(+), 7 deletions(-) create mode 100644 compiler/test/compilable/imports/imp20344.c create mode 100644 compiler/test/compilable/test20344.d diff --git a/compiler/src/dmd/astbase.d b/compiler/src/dmd/astbase.d index e0a1808e78..06eab18223 100644 --- a/compiler/src/dmd/astbase.d +++ b/compiler/src/dmd/astbase.d @@ -4954,6 +4954,8 @@ struct ASTBase /// If the string is parsed from a hex string literal bool hexString = false; + /// If the string is from a collected C macro + bool cMacro = false; extern (D) this(Loc loc, const(void)[] string) { @@ -4963,13 +4965,14 @@ struct ASTBase 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)); this.string = cast(char*)string; this.len = len; this.postfix = postfix; this.sz = 1; // work around LDC bug #1286 + this.cMacro = cMacro; } /********************************************** diff --git a/compiler/src/dmd/cparse.d b/compiler/src/dmd/cparse.d index f3b863c324..9ef2abc5eb 100644 --- a/compiler/src/dmd/cparse.d +++ b/compiler/src/dmd/cparse.d @@ -6193,7 +6193,7 @@ final class CParser(AST) : Parser!AST /* Declare manifest constant: * 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); addSym(v); ++p; diff --git a/compiler/src/dmd/expression.d b/compiler/src/dmd/expression.d index 8cb28cc208..9207a0942d 100644 --- a/compiler/src/dmd/expression.d +++ b/compiler/src/dmd/expression.d @@ -1406,6 +1406,8 @@ extern (C++) final class StringExp : Expression /// If the string is parsed from a hex string literal bool hexString = false; + /// If the string is from a collected C macro + bool cMacro = false; enum char NoPostfix = 0; @@ -1417,13 +1419,14 @@ extern (C++) final class StringExp : Expression 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_); this.string = cast(char*)string.ptr; // note that this.string should be const this.len = len; this.sz = sz; this.postfix = postfix; + this.cMacro = cMacro; } static StringExp create(Loc loc, const(char)* s) diff --git a/compiler/src/dmd/expression.h b/compiler/src/dmd/expression.h index 14dc7ad4ec..9bd0c7994d 100644 --- a/compiler/src/dmd/expression.h +++ b/compiler/src/dmd/expression.h @@ -353,6 +353,7 @@ public: unsigned char sz; // 1: char, 2: wchar, 4: dchar d_bool committed; // if type is committed 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 void *s, d_size_t len); diff --git a/compiler/src/dmd/expressionsem.d b/compiler/src/dmd/expressionsem.d index e5f9e301a2..d97f96e653 100644 --- a/compiler/src/dmd/expressionsem.d +++ b/compiler/src/dmd/expressionsem.d @@ -4429,7 +4429,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor } buffer.write4(0); e.setData(buffer.extractData(), newlen, 4); - if (sc && sc.inCfile) + if (!e.cMacro && sc && sc.inCfile) e.type = Type.tuns32.sarrayOf(e.len + 1); else e.type = Type.tdchar.immutableOf().arrayOf(); @@ -4454,7 +4454,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor } buffer.writeUTF16(0); e.setData(buffer.extractData(), newlen, 2); - if (sc && sc.inCfile) + if (!e.cMacro && sc && sc.inCfile) e.type = Type.tuns16.sarrayOf(e.len + 1); else e.type = Type.twchar.immutableOf().arrayOf(); @@ -4466,7 +4466,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor goto default; default: - if (sc && sc.inCfile) + if (!e.cMacro && sc && sc.inCfile) e.type = Type.tchar.sarrayOf(e.len + 1); else e.type = Type.tchar.immutableOf().arrayOf(); diff --git a/compiler/src/dmd/frontend.h b/compiler/src/dmd/frontend.h index 44a370492c..85f946061b 100644 --- a/compiler/src/dmd/frontend.h +++ b/compiler/src/dmd/frontend.h @@ -3608,6 +3608,7 @@ public: uint8_t sz; bool committed; bool hexString; + bool cMacro; enum : char { NoPostfix = 0u }; static StringExp* create(Loc loc, const char* s); @@ -5548,7 +5549,7 @@ private: char realexp[48LLU]; char complexexp[64LLU]; char symoffexp[56LLU]; - char stringexp[43LLU]; + char stringexp[44LLU]; char arrayliteralexp[40LLU]; char assocarrayliteralexp[48LLU]; char structliteralexp[64LLU]; diff --git a/compiler/test/compilable/imports/imp20344.c b/compiler/test/compilable/imports/imp20344.c new file mode 100644 index 0000000000..56ac79c930 --- /dev/null +++ b/compiler/test/compilable/imports/imp20344.c @@ -0,0 +1,2 @@ +// https://github.com/dlang/dmd/issues/20334 +#define X "X" diff --git a/compiler/test/compilable/test20344.d b/compiler/test/compilable/test20344.d new file mode 100644 index 0000000000..26ee9a3269 --- /dev/null +++ b/compiler/test/compilable/test20344.d @@ -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); +}