Skip to content

Commit f10ddb4

Browse files
committed
Fix #23241 - duplicate deprecation message for enum member accessed by name
A deprecated enum member accessed by its unqualified name (an anonymous enum member, a member found via `with`, or an ImportC enumerator) reported the deprecation twice: once during name resolution and again in getVarExp(), which already performs the deprecated/disabled checks itself. Skip the redundant check for enum members in the two name-resolution paths so the diagnostic is emitted exactly once.
1 parent 940287b commit f10ddb4

2 files changed

Lines changed: 33 additions & 6 deletions

File tree

compiler/src/dmd/expressionsem.d

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2703,7 +2703,9 @@ Lagain:
27032703
{
27042704
// functions are checked after overloading
27052705
// templates are checked after matching constraints
2706-
if (!s.isFuncDeclaration() && !s.isTemplateDeclaration())
2706+
// enum members are checked once in getVarExp() below; skip here to avoid
2707+
// emitting the deprecation diagnostic twice for an enum member accessed by name
2708+
if (!s.isFuncDeclaration() && !s.isTemplateDeclaration() && !s.isEnumMember())
27072709
{
27082710
s.checkDeprecated(loc, sc);
27092711
if (d)
@@ -2715,7 +2717,7 @@ Lagain:
27152717
s = s.toAlias();
27162718

27172719
//printf("s = '%s', s.kind = '%s', s.needThis() = %p\n", s.toChars(), s.kind(), s.needThis());
2718-
if (s != olds && !s.isFuncDeclaration() && !s.isTemplateDeclaration())
2720+
if (s != olds && !s.isFuncDeclaration() && !s.isTemplateDeclaration() && !s.isEnumMember())
27192721
{
27202722
s.checkDeprecated(loc, sc);
27212723
if (d)
@@ -16006,14 +16008,18 @@ Expression dotIdSemanticProp(DotIdExp exp, Scope* sc, bool gag)
1600616008
// if 's' is a tuple variable, the tuple is returned.
1600716009
s = s.toAlias();
1600816010

16009-
s.checkDeprecated(exp.loc, sc);
16010-
if (auto d = s.isDeclaration())
16011-
d.checkDisabled(exp.loc, sc);
16012-
1601316011
if (auto em = s.isEnumMember())
1601416012
{
16013+
// getVarExp() performs the deprecated/disabled checks itself; doing them
16014+
// here as well would emit the diagnostic twice for an enum member
16015+
// accessed by name (e.g. an anonymous enum member, or an ImportC enumerator).
1601516016
return em.getVarExp(exp.loc, sc);
1601616017
}
16018+
16019+
s.checkDeprecated(exp.loc, sc);
16020+
if (auto d = s.isDeclaration())
16021+
d.checkDisabled(exp.loc, sc);
16022+
1601716023
if (auto v = s.isVarDeclaration())
1601816024
{
1601916025
//printf("DotIdExp:: Identifier '%s' is a variable, type '%s'\n", toChars(), v.type.toErrMsg());
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/*
2+
REQUIRED_ARGS: -verrors=simple
3+
TEST_OUTPUT:
4+
---
5+
compilable/deprecated_enum_member.d(20): Deprecation: enum member `deprecated_enum_member.anon` is deprecated
6+
compilable/deprecated_enum_member.d(17): `anon` is declared here
7+
compilable/deprecated_enum_member.d(21): Deprecation: enum member `deprecated_enum_member.E.named` is deprecated
8+
compilable/deprecated_enum_member.d(18): `named` is declared here
9+
---
10+
*/
11+
12+
// A deprecated enum member accessed by name must emit the deprecation diagnostic
13+
// exactly once. Previously an anonymous-enum member (or an ImportC enumerator)
14+
// accessed by its unqualified name reported the deprecation twice, because the symbol
15+
// was checked both during name resolution and again in getVarExp().
16+
17+
enum { deprecated anon = 0, anonB }
18+
enum E { deprecated named = 0, namedB }
19+
20+
int useAnon() { return anon; }
21+
int useNamed() { return E.named; }

0 commit comments

Comments
 (0)