From 9ff8980a063c1320d341bc39f463300ce5a854f5 Mon Sep 17 00:00:00 2001 From: Tim Schendekehl Date: Sat, 17 Aug 2024 16:14:05 +0200 Subject: [PATCH] Fix bugzilla 24639 - ImportC: defines of negative constants not detected for enum conversion (#16789) Negative expressions inside parens are already supported. This adds support for defines with negative numbers without parens, but not more complex expressions. Defines for negative numbers are often used as error codes in C. --- compiler/src/dmd/cparse.d | 28 ++++++++++++++++++++++ compiler/test/compilable/imports/defines.c | 8 +++++++ compiler/test/compilable/testdefines.d | 14 +++++++++++ 3 files changed, 50 insertions(+) diff --git a/compiler/src/dmd/cparse.d b/compiler/src/dmd/cparse.d index a4e3c7ecc035..80b5c9aa79b1 100644 --- a/compiler/src/dmd/cparse.d +++ b/compiler/src/dmd/cparse.d @@ -5956,6 +5956,30 @@ final class CParser(AST) : Parser!AST AST.Type t; + bool hasMinus; + if (token.value == TOK.min) + { + nextToken(); + // Only allow integer and float literals after minus. + switch (token.value) + { + case TOK.int32Literal: + case TOK.uns32Literal: + case TOK.int64Literal: + case TOK.uns64Literal: + case TOK.float32Literal: + case TOK.float64Literal: + case TOK.float80Literal: + case TOK.imaginary32Literal: + case TOK.imaginary64Literal: + case TOK.imaginary80Literal: + hasMinus = true; + break; + default: + continue; + } + } + Lswitch: switch (token.value) { @@ -5980,6 +6004,8 @@ final class CParser(AST) : Parser!AST * enum id = intvalue; */ AST.Expression e = new AST.IntegerExp(scanloc, intvalue, t); + if (hasMinus) + e = new AST.NegExp(scanloc, e); auto v = new AST.VarDeclaration(scanloc, t, id, new AST.ExpInitializer(scanloc, e), STC.manifest); addSym(v); ++p; @@ -6003,6 +6029,8 @@ final class CParser(AST) : Parser!AST * enum id = floatvalue; */ AST.Expression e = new AST.RealExp(scanloc, floatvalue, t); + if (hasMinus) + e = new AST.NegExp(scanloc, e); auto v = new AST.VarDeclaration(scanloc, t, id, new AST.ExpInitializer(scanloc, e), STC.manifest); addSym(v); ++p; diff --git a/compiler/test/compilable/imports/defines.c b/compiler/test/compilable/imports/defines.c index 6b0746f8ff96..420679a4fccb 100644 --- a/compiler/test/compilable/imports/defines.c +++ b/compiler/test/compilable/imports/defines.c @@ -55,3 +55,11 @@ int pr16199c() { return 8; } + +// https://issues.dlang.org/show_bug.cgi?id=24639 +#define NEGATIVE_I32 -1 +#define NEGATIVE_U32 -2U +#define NEGATIVE_I64 -3LL +#define NEGATIVE_U64 -4LLU +#define NEGATIVE_F32 -5.0f +#define NEGATIVE_F64 -6.0 diff --git a/compiler/test/compilable/testdefines.d b/compiler/test/compilable/testdefines.d index 060e962920a6..58eefb7256a3 100644 --- a/compiler/test/compilable/testdefines.d +++ b/compiler/test/compilable/testdefines.d @@ -25,3 +25,17 @@ static assert(pr16199_ice == 3); static assert(pr16199d() == 7); static assert(pr16199c() == 8); + +// https://issues.dlang.org/show_bug.cgi?id=24639 +static assert(NEGATIVE_I32 == -1); +static assert(NEGATIVE_U32 == cast(uint)-2); +static assert(NEGATIVE_I64 == -3); +static assert(NEGATIVE_U64 == cast(ulong)-4L); +static assert(NEGATIVE_F32 == -5f); +static assert(NEGATIVE_F64 == -6); +static assert(is(typeof(NEGATIVE_I32) == int)); +static assert(is(typeof(NEGATIVE_U32) == uint)); +static assert(is(typeof(NEGATIVE_I64) == long)); +static assert(is(typeof(NEGATIVE_U64) == ulong)); +static assert(is(typeof(NEGATIVE_F32) == float)); +static assert(is(typeof(NEGATIVE_F64) == double));