[cfe-dev] No warning when lambda returns reference to temporary

Matthew Urquhart via cfe-dev cfe-dev at lists.llvm.org
Thu Jul 13 02:23:46 PDT 2017


Hi Csaba,

Thanks very much for the reply - makes sense. I was originally having
trouble with strings, but switched to ints for a shorter "minimal case."

In this case since the lambda returns an `int`, it's now
`std::function<int()>` not `std::function<const int&()>` which on the
surface seems it should be a mismatching type.

Minimal case updated for strings below. Strangely, it works correctly on
macOS but invokes undefined behaviour on ubuntu.

Cheers,
Matt

#include <functional>

#include <iostream>

#include <sstream>


void print_stuff(std::function<const std::string&()> f) {

    std::cout << "stuff is: " << f() << std::endl;

}


int main(int argc, char *argv[]) {

    print_stuff([&]() {

        std::stringstream ss;

        ss << argc;

        return ss.str();

    });

}

On Thu, Jul 13, 2017 at 5:08 PM Csaba Raduly <rcsaba at gmail.com> wrote:

> Hi Matthew,
>
> When you don't specify a return type for the lambda, the compiler
> deduces 'int', not 'int&'.
>
> auto deduced     = []()         { int i = 123; return i; };
> auto spelled_out = []() -> int& { int i = 123; return i; };
>
> int d = deduced;
> int s = spelled_out;
>
> This doesn't compile of course, but the error messages are the useful info:
>
> $ g++-8 -std=c++11 is_it_ref.cpp
> is_it_ref.cpp: In lambda function:
> is_it_ref.cpp:2:39: warning: reference to local variable ‘i’ returned
> [-Wreturn-local-addr]
>  auto spelled_out = []() -> int& { int i = 123; return i; };
>                                        ^
> is_it_ref.cpp: At global scope:
> is_it_ref.cpp:4:9: error: invalid user-defined conversion from
> ‘<lambda()>’ to ‘int’ [-fpermissive]
>  int d = deduced;
>          ^~~~~~~
> is_it_ref.cpp:1:23: note: candidate is: ‘<lambda()>::operator int
> (*)()() const’ <near match>
>  auto deduced     = []()         { int i = 123; return i; };
>                        ^
> is_it_ref.cpp:1:23: note:   no known conversion from ‘int (*)()’ to ‘int’
> is_it_ref.cpp:5:9: error: invalid user-defined conversion from
> ‘<lambda()>’ to ‘int’ [-fpermissive]
>  int s = spelled_out;
>          ^~~~~~~~~~~
> is_it_ref.cpp:2:31: note: candidate is: ‘<lambda()>::operator int&
> (*)()() const’ <near match>
>  auto spelled_out = []() -> int& { int i = 123; return i; };
>                                ^
> is_it_ref.cpp:2:31: note:   no known conversion from ‘int& (*)()’ to ‘int’
>
>
> On Thu, Jul 13, 2017 at 6:55 AM, Matthew Urquhart via cfe-dev
> <cfe-dev at lists.llvm.org> wrote:
> > Hiya,
> >
> > I ran into this (presumably) undefined behaviour today, and wonder if
> it's a
> > bug or expected. My app was coded similarly and ran correctly on
> macOS/LLVM
> > version 8.1.0 (clang-802.0.38) but not Ubuntu14.04/gcc-4.7.3-12ubuntu1
> >
> > In the case of this code, it's invalid since the lambda returns a
> reference
> > to a temp object. My bad, I'll fix it. Seems the compiler could've
> warned me
> > though :)
> >
> > Compiler warns when explicitly specifying the return type of the lambda
> > using `->` operator, but not when implicit. Is this expected or a bug?
> >
> > Thanks in advance,
> > Matt
> >
> > // Minimal test case:
> >
> > #include <functional>
> >
> > #include <iostream>
> >
> >
> > void print_stuff(std::function<const int&()> f) {
> >
> >     std::cout << "stuff is: " << f() << std::endl;
> >
> > }
> >
> >
> > int main(int argc, char *argv[]) {
> >
> >     print_stuff([]() {
> >
> >         int i = 123;
> >
> >         return i;
> >
> >     });
> >
> > }
> >
> >
> > _______________________________________________
> > cfe-dev mailing list
> > cfe-dev at lists.llvm.org
> > http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
> >
>
>
>
> --
> GCS a+ e++ d- C++ ULS$ L+$ !E- W++ P+++$ w++$ tv+ b++ DI D++ 5++
> The Tao of math: The numbers you can count are not the real numbers.
> Life is complex, with real and imaginary parts.
> "Ok, it boots. Which means it must be bug-free and perfect. " -- Linus
> Torvalds
> "People disagree with me. I just ignore them." -- Linus Torvalds
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20170713/122336b0/attachment.html>


More information about the cfe-dev mailing list