This does not depend on the gcc version, but rather on the C++-Standard Version you're compiling for.
Your example works without problems with the latest gcc version when compiling for C++03: godbolt
The reason why this compiles at all is that pre-C++11 there was no bool datatype.
Checking if a stream is valid (e.g. if(stream) { /*...*/ }) therefore was mandated to just return some unspecified boolean-like type:
cppreference
operator /* unspecified-boolean-type */() const; // (until C++11)
explicit operator bool() const; // (since C++11)
Note that the conversion also was implicit pre C++11, since explicit conversion functions were added in C++11.
libstdc++ happens to define the conversion operator as follows: github
///@{
/**
 *  @brief  The quick-and-easy status check.
 *
 *  This allows you to write constructs such as
 *  <code>if (!a_stream) ...</code> and <code>while (a_stream) ...</code>
 */
#if __cplusplus >= 201103L
      explicit operator bool() const { return !this->fail(); }
#else
      operator void*() const { return this->fail() ? 0 : const_cast<basic_ios*>(this); }
#endif
Note that this allows an implicit (!) conversion from any stream to void*.
Which is unfortunate, given that std::basic_ostream provides an overload for outputting pointers:
cppreference
basic_ostream& operator<<( const void* value ); // (8)
So what actually happens in your example is that the stream is implicitly converted to a void* pointer, and then operator<<(const void*) is called to output that pointer.
Which is probably not what you wanted to happen:
godbolt
#include <iostream>
#include <sstream>
int main() {
    std::stringstream m;
    m << "foobar";
    std::stringstream ss;
    // equivalent to  ss << static_cast<void*>(&m);
    ss << m;
    std::cout << ss.str() << std::endl;
    // will print the address of m, e.g. 0x7ffcda4c2540
    // NOT foobar!
    return 0;
}
The correct way to append a stream
C++ std::istreams can be written to std::ostreams by just passing the underlying stream buffer instead of the whole stream, e.g.:
godbolt
#include <iostream>
#include <sstream>
int main() {
    std::stringstream m;
    m << "foobar";
    std::stringstream ss;
    ss << m.rdbuf(); // append everything from m to ss
    std::cout << ss.str() << std::endl;
    return 0;
}
So your example could be fixed like this:
// r << m;
r << m.rdbuf();