From d24a8859b090911a2a48cbbd7666ff7e448acfc8 Mon Sep 17 00:00:00 2001 From: Paul Backus Date: Fri, 3 Nov 2023 09:17:37 -0400 Subject: [PATCH] Fix Issue 24224 - __traits(initSymbol) treats aggregate-derived enum as base type (#15776) --- compiler/src/dmd/traits.d | 16 ++++++++++++---- compiler/test/fail_compilation/fail24224.d | 22 ++++++++++++++++++++++ 2 files changed, 34 insertions(+), 4 deletions(-) create mode 100644 compiler/test/fail_compilation/fail24224.d diff --git a/compiler/src/dmd/traits.d b/compiler/src/dmd/traits.d index ca2af79dde..7489f99aa9 100644 --- a/compiler/src/dmd/traits.d +++ b/compiler/src/dmd/traits.d @@ -1875,16 +1875,24 @@ Expression semanticTraits(TraitsExp e, Scope* sc) return dimError(1); auto o = (*e.args)[0]; - Type t = isType(o); - AggregateDeclaration ad = t ? isAggregate(t) : null; - // Interfaces don't have an init symbol and hence cause linker errors - if (!ad || ad.isInterfaceDeclaration()) + ErrorExp badArgument() { error(e.loc, "struct / class type expected as argument to __traits(initSymbol) instead of `%s`", o.toChars()); return ErrorExp.get(); } + Type t = isType(o); + + if (!t || t.isTypeEnum()) + return badArgument(); + + AggregateDeclaration ad = isAggregate(t); + + // Interfaces don't have an init symbol and hence cause linker errors + if (!ad || ad.isInterfaceDeclaration()) + return badArgument(); + Declaration d = new SymbolDeclaration(ad.loc, ad); d.type = Type.tvoid.arrayOf().constOf(); d.storage_class |= STC.rvalue; diff --git a/compiler/test/fail_compilation/fail24224.d b/compiler/test/fail_compilation/fail24224.d new file mode 100644 index 0000000000..db87f5305d --- /dev/null +++ b/compiler/test/fail_compilation/fail24224.d @@ -0,0 +1,22 @@ +/+ +TEST_OUTPUT: +--- +fail_compilation/fail24224.d(19): Error: struct / class type expected as argument to __traits(initSymbol) instead of `ES` +fail_compilation/fail24224.d(20): Error: struct / class type expected as argument to __traits(initSymbol) instead of `EU` +fail_compilation/fail24224.d(21): Error: struct / class type expected as argument to __traits(initSymbol) instead of `EC` +--- ++/ +struct S {} +union U {} +class C {} + +enum ES : S { a = S.init } +enum EU : U { a = U.init } +enum EC : C { a = C.init } + +void test() +{ + auto init1 = __traits(initSymbol, ES); + auto init2 = __traits(initSymbol, EU); + auto init3 = __traits(initSymbol, EC); +}