diff --git a/compiler/src/dmd/declaration.h b/compiler/src/dmd/declaration.h index 27a68e0abcd7..4ac22b935887 100644 --- a/compiler/src/dmd/declaration.h +++ b/compiler/src/dmd/declaration.h @@ -638,12 +638,10 @@ class FuncDeclaration : public Declaration bool nothrowInprocess(bool v); bool nogcInprocess() const; bool nogcInprocess(bool v); - bool returnInprocess() const; - bool returnInprocess(bool v); + bool scopeInprocess() const; + bool scopeInprocess(bool v); bool inlineScanned() const; bool inlineScanned(bool v); - bool inferScope() const; - bool inferScope(bool v); bool hasCatches() const; bool hasCatches(bool v); bool skipCodegen() const; diff --git a/compiler/src/dmd/escape.d b/compiler/src/dmd/escape.d index 3b55bee29265..de08b0d30827 100644 --- a/compiler/src/dmd/escape.d +++ b/compiler/src/dmd/escape.d @@ -1320,7 +1320,7 @@ private bool checkReturnEscapeImpl(ref Scope sc, Expression e, bool refs, bool g return; } FuncDeclaration fd = p.isFuncDeclaration(); - if (fd && sc.func.returnInprocess) + if (fd && sc.func.scopeInprocess) { /* Code like: * int x; @@ -1448,7 +1448,7 @@ private bool inferReturn(FuncDeclaration fd, VarDeclaration v, bool returnScope) if (!v.isParameter() || v.isTypesafeVariadicArray || (returnScope && v.doNotInferReturn)) return false; - if (!fd.returnInprocess) + if (!fd.scopeInprocess) return false; if (returnScope && !(v.isScope() || v.maybeScope)) @@ -2073,24 +2073,20 @@ private void doNotInferScope(VarDeclaration v, RootObject o) public void finishScopeParamInference(FuncDeclaration funcdecl, ref TypeFunction f) { + if (!funcdecl.scopeInprocess) + return; + funcdecl.scopeInprocess = false; - if (funcdecl.returnInprocess) + if (funcdecl.storage_class & STC.return_) { - funcdecl.returnInprocess = false; - if (funcdecl.storage_class & STC.return_) - { - if (funcdecl.type == f) - f = cast(TypeFunction)f.copy(); - f.isreturn = true; - f.isreturnscope = cast(bool) (funcdecl.storage_class & STC.returnScope); - if (funcdecl.storage_class & STC.returninferred) - f.isreturninferred = true; - } + if (funcdecl.type == f) + f = cast(TypeFunction)f.copy(); + f.isreturn = true; + f.isreturnscope = cast(bool) (funcdecl.storage_class & STC.returnScope); + if (funcdecl.storage_class & STC.returninferred) + f.isreturninferred = true; } - if (!funcdecl.inferScope) - return; - funcdecl.inferScope = false; // Infer STC.scope_ if (funcdecl.parameters && !funcdecl.errors) diff --git a/compiler/src/dmd/frontend.h b/compiler/src/dmd/frontend.h index a2d876cb582e..3d273b93d180 100644 --- a/compiler/src/dmd/frontend.h +++ b/compiler/src/dmd/frontend.h @@ -3698,12 +3698,10 @@ class FuncDeclaration : public Declaration bool nothrowInprocess(bool v); bool nogcInprocess() const; bool nogcInprocess(bool v); - bool returnInprocess() const; - bool returnInprocess(bool v); + bool scopeInprocess() const; + bool scopeInprocess(bool v); bool inlineScanned() const; bool inlineScanned(bool v); - bool inferScope() const; - bool inferScope(bool v); bool hasCatches() const; bool hasCatches(bool v); bool skipCodegen() const; diff --git a/compiler/src/dmd/func.d b/compiler/src/dmd/func.d index f93c60b1f800..c815c5892356 100644 --- a/compiler/src/dmd/func.d +++ b/compiler/src/dmd/func.d @@ -119,9 +119,8 @@ private struct FUNCFLAG bool safetyInprocess; /// working on determining safety bool nothrowInprocess; /// working on determining nothrow bool nogcInprocess; /// working on determining @nogc - bool returnInprocess; /// working on inferring 'return' for parameters + bool scopeInprocess; /// infer `return` and `scope` for parameters bool inlineScanned; /// function has been scanned for inline possibilities - bool inferScope; /// infer 'scope' for parameters bool hasCatches; /// function has try-catch statements bool skipCodegen; /// do not generate code for this function. bool printf; /// is a printf-like function @@ -722,11 +721,8 @@ extern (C++) class FuncDeclaration : Declaration if (!tf.isnogc) nogcInprocess = true; - if (!isVirtual() || this.isIntroducing()) - returnInprocess = true; - // Initialize for inferring STC.scope_ - inferScope = true; + scopeInprocess = true; } extern (D) final uint saveFlags() @@ -1674,7 +1670,7 @@ extern (C++) final class FuncLiteralDeclaration : FuncDeclaration this.fes = fes; // Always infer scope for function literals // See https://issues.dlang.org/show_bug.cgi?id=20362 - this.inferScope = true; + this.scopeInprocess = true; //printf("FuncLiteralDeclaration() id = '%s', type = '%s'\n", this.ident.toChars(), type.toChars()); } diff --git a/compiler/test/fail_compilation/test24680.d b/compiler/test/fail_compilation/test24680.d new file mode 100644 index 000000000000..50efba41344e --- /dev/null +++ b/compiler/test/fail_compilation/test24680.d @@ -0,0 +1,20 @@ +/** +REQUIRED_ARGS: -preview=dip1000 +TEST_OUTPUT: +--- +fail_compilation/test24680.d(19): Error: returning `c.peek(buf[])` escapes a reference to local variable `buf` +--- +*/ + +// https://issues.dlang.org/show_bug.cgi?id=24680 + +class C +{ + final auto peek(ubyte[] buf) { return buf; } +} + +@safe escape(C c) +{ + ubyte[5] buf; + return c.peek(buf[]); +}