diff --git a/src/dmd/dscope.d b/src/dmd/dscope.d index 25ccf89e226f..86944515891b 100644 --- a/src/dmd/dscope.d +++ b/src/dmd/dscope.d @@ -807,4 +807,28 @@ struct Scope else return STRUCTALIGN_DEFAULT; } + + /********************************** + * Checks whether the current scope (or any of its parents) is deprecated. + * + * Returns: `true` if this or any parent scope is deprecated, `false` otherwise` + */ + extern(C++) bool isDeprecated() + { + for (Dsymbol sp = this.parent; sp; sp = sp.parent) + { + if (sp.isDeprecated()) + return true; + } + for (Scope* sc2 = &this; sc2; sc2 = sc2.enclosing) + { + if (sc2.scopesym && sc2.scopesym.isDeprecated()) + return true; + + // If inside a StorageClassDeclaration that is deprecated + if (sc2.stc & STC.deprecated_) + return true; + } + return false; + } } diff --git a/src/dmd/dsymbol.d b/src/dmd/dsymbol.d index 2ecd1f9131c2..943181cc8973 100644 --- a/src/dmd/dsymbol.d +++ b/src/dmd/dsymbol.d @@ -310,20 +310,9 @@ extern (C++) class Dsymbol : RootObject if (global.params.useDeprecated != 1 && isDeprecated()) { // Don't complain if we're inside a deprecated symbol's scope - for (Dsymbol sp = sc.parent; sp; sp = sp.parent) - { - if (sp.isDeprecated()) - return false; - } - for (Scope* sc2 = sc; sc2; sc2 = sc2.enclosing) - { - if (sc2.scopesym && sc2.scopesym.isDeprecated()) - return false; + if (sc.isDeprecated()) + return false; - // If inside a StorageClassDeclaration that is deprecated - if (sc2.stc & STC.deprecated_) - return false; - } const(char)* message = null; for (Dsymbol p = this; p; p = p.parent) { diff --git a/src/dmd/dsymbolsem.d b/src/dmd/dsymbolsem.d index 8c54df09a59e..5b54989e8358 100644 --- a/src/dmd/dsymbolsem.d +++ b/src/dmd/dsymbolsem.d @@ -383,7 +383,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor //printf("storage_class = x%x\n", storage_class); if (global.params.vcomplex) - dsym.type.checkComplexTransition(dsym.loc); + dsym.type.checkComplexTransition(dsym.loc, sc); // Calculate type size + safety checks if (sc.func && !sc.intypeof) diff --git a/src/dmd/expressionsem.d b/src/dmd/expressionsem.d index f3fcbf4a91ee..b0eb45355d03 100644 --- a/src/dmd/expressionsem.d +++ b/src/dmd/expressionsem.d @@ -1856,7 +1856,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor assert(0); if (global.params.vcomplex) - exp.type.checkComplexTransition(exp.loc); + exp.type.checkComplexTransition(exp.loc, sc); result = e; } @@ -3774,7 +3774,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor } if (global.params.vcomplex) - ta.checkComplexTransition(exp.loc); + ta.checkComplexTransition(exp.loc, sc); Expression e; if (ea && ta.toBasetype().ty == Tclass) diff --git a/src/dmd/mtype.d b/src/dmd/mtype.d index 1edc051ade25..06a5ac9369df 100644 --- a/src/dmd/mtype.d +++ b/src/dmd/mtype.d @@ -3009,16 +3009,20 @@ extern (C++) abstract class Type : RootObject * Should only give alerts when set to emit transitional messages. * Params: * loc = The source location. + * sc = scope of the type */ - final void checkComplexTransition(Loc loc) + final bool checkComplexTransition(Loc loc, Scope* sc) { + if (sc.isDeprecated()) + return false; + Type t = baseElemOf(); while (t.ty == Tpointer || t.ty == Tarray) t = t.nextOf().baseElemOf(); // Basetype is an opaque enum, nothing to check. if (t.ty == Tenum && !(cast(TypeEnum)t).sym.memtype) - return; + return false; if (t.isimaginary() || t.iscomplex()) { @@ -3047,13 +3051,16 @@ extern (C++) abstract class Type : RootObject { deprecation(loc, "use of complex type `%s` is deprecated, use `std.complex.Complex!(%s)` instead", toChars(), rt.toChars()); + return true; } else { deprecation(loc, "use of imaginary type `%s` is deprecated, use `%s` instead", toChars(), rt.toChars()); + return true; } } + return false; } static void error(Loc loc, const(char)* format, ...) diff --git a/src/dmd/mtype.h b/src/dmd/mtype.h index 6de35667ca95..a7077524f439 100644 --- a/src/dmd/mtype.h +++ b/src/dmd/mtype.h @@ -336,7 +336,7 @@ class Type : public RootObject uinteger_t sizemask(); virtual bool needsDestruction(); virtual bool needsNested(); - void checkComplexTransition(Loc loc); + bool checkComplexTransition(Loc loc, Scope *sc); static void error(Loc loc, const char *format, ...); static void warning(Loc loc, const char *format, ...); diff --git a/src/dmd/scope.h b/src/dmd/scope.h index 81d1267dda7f..28895841def9 100644 --- a/src/dmd/scope.h +++ b/src/dmd/scope.h @@ -158,6 +158,8 @@ struct Scope void setNoFree(); structalign_t alignment(); + + bool isDeprecated(); }; #endif /* DMD_SCOPE_H */ diff --git a/src/dmd/semantic3.d b/src/dmd/semantic3.d index cdc59d68e3b3..a7003787634a 100644 --- a/src/dmd/semantic3.d +++ b/src/dmd/semantic3.d @@ -581,7 +581,7 @@ private extern(C++) final class Semantic3Visitor : Visitor funcdecl.fbody = new ErrorStatement(); } if (global.params.vcomplex && f.next !is null) - f.next.checkComplexTransition(funcdecl.loc); + f.next.checkComplexTransition(funcdecl.loc, sc); if (funcdecl.returns && !funcdecl.fbody.isErrorStatement()) { diff --git a/test/compilable/sw_transition_complex.d b/test/compilable/sw_transition_complex.d index 46650cf294d4..e6090b1d78e4 100644 --- a/test/compilable/sw_transition_complex.d +++ b/test/compilable/sw_transition_complex.d @@ -141,3 +141,16 @@ struct S; void test14488c(E *e, S *s) { } + +// Issue 18212 - Usage of cfloat,cdouble,cfloat,ifloat,idouble,ireal shouldn't trigger an error in deprecated code +deprecated void test18212(creal c){} +deprecated unittest +{ + ireal = 2i; + creal = 2 + 3i; +} +deprecated struct Foo +{ + ifloat a = 2i; + cfloat b = 2f + 2i; +}