diff --git a/src/dmd/statementsem.d b/src/dmd/statementsem.d index c4fe2e1b94d9..e8cab5c4d52c 100644 --- a/src/dmd/statementsem.d +++ b/src/dmd/statementsem.d @@ -3060,16 +3060,25 @@ else { /* Determine "refness" of function return: * if it's an lvalue, return by ref, else return by value + * https://dlang.org/spec/function.html#auto-ref-functions */ + + void turnOffRef() + { + tf.isref = false; // return by value + tf.isreturn = false; // ignore 'return' attribute, whether explicit or inferred + fd.storage_class &= ~STC.return_; + } + if (rs.exp.isLvalue()) { /* May return by ref */ if (checkReturnEscapeRef(sc, rs.exp, true)) - tf.isref = false; // return by value + turnOffRef(); } else - tf.isref = false; // return by value + turnOffRef(); /* The "refness" is determined by all of return statements. * This means: diff --git a/test/compilable/test17512.d b/test/compilable/test17512.d new file mode 100644 index 000000000000..93b11940a95f --- /dev/null +++ b/test/compilable/test17512.d @@ -0,0 +1,15 @@ +// https://issues.dlang.org/show_bug.cgi?id=17512 + +struct A +{ + int _value; + + bool _hasValue; + + auto ref getOr(int alternativeValue) + { + return _hasValue ? _value : alternativeValue; + } +} + +A a;