Search code examples
c++c++17compiler-warningstemporary-objectsstring-view

Is there a way to get a compiler warning when returning a by-value string_view from a temporary?


I’ve been learning c++17 changes by applying them to some old code, and found that returning std::string_view produces silent bugs, and it seems to me that a reference to temporary compiler warning would be appropriate. Is there a way I can generate one?

I am using g++ 9.3.0, with compiler flags -ggdb -Wall -std=c++17. I also tried clang and clang-tidy/clazy without a warning.

First of all, I have recently learned that it’s probably best to only use std::string_view to replace const std::string & in parameters, and not as a return value. This article explained it pretty well to me. Unfortunately I’m not seeing it generally presented that way, so I wonder if others are having the same issue.

(section 1 in the code below) I know that attempting to return a non-const reference to a temporary string will not compile. The same is true whether that reference is a std::string & or a std::string_view &.

The same compiler error occurs if I attempt to return a non-const std::string_view & reference to the permanent string theString.

(section 2 in the code below) I also know that if I attempt to return a const reference to a temporary string, it will compile, but the compiler will provide a warning that I have returned a reference to a temporary. As in section 1, the same is true whether that reference is a const std::string & or a const std::string_view &.

Also as in section 1, the same reference to temporary compiler warning occurs if I attempt to return a const std::string_view & reference to the permanent string theString.

(section 3 in the code below) If I try to return a std::string_view from a permanent, or from a reference to a permanent, it works fine, of course, but if I try to return from a temporary, it compiles without warning, but its use produces garbage.

Shouldn’t the compiler produce the same reference to temporary warning as in section 2 of the code? Sure, it’s not a reference per se, but then theString is not a temporary, and that warning was applied there. Is there a way I can generate such a warning? Perhaps a compiler option I’m missing for either g++ or clang-tidy?

#include <string>
#include <string_view>
#include <iostream>

class C1
{
public:
    C1() { theString = "Initial string."; }

    //  produce a temporary std::string
    std::string getS() { return theString; }
    //  Returning string_view works fine if called on a reference to a permenant string.
    std::string &getRef() { return theString; }

//  SECTION1: These won't compile: can't bind non-const lvalue reference to the rvalue
//     std::string &getSref() { return getS(); }
//     std::string_view &getSVref() { return getS(); }
//     std::string_view &getSVref() { return theString; }

//  SECTION2: These produce compiler warning: reference to temporary, and use gives seg fault
    const std::string &getSref() { return getS(); }
    const std::string_view &getSVrefFromTemp() { return getS(); }
    //  also produces compiler warning: reference to temporary, 
    //      even though theString is not temporary
    const std::string_view &getSVrefFromPerm() { return theString; }

//  SECTION3:  
    std::string_view getSVfromPerm() { return theString; }  //  works fine
    std::string_view getSVfromRef() { return getRef(); }    //  works fine
    std::string_view getSVfromTemp() { return getS(); }     //  silent bug.

private:
    std::string theString;
};

int main()
{
    C1 myClass;

//  SECTION2: produces seg fault
//     std::cout << "getSref: \"" << myClass.getSref() << "\"." << std::endl;
//     std::cout << "getSVrefFromTemp: \"" << myClass.getSVrefFromTemp() << "\"." << std::endl;
//     std::cout << "getSVrefFromPerm: \"" << myClass.getSVrefFromPerm() << "\"." << std::endl;

//  SECTION3:  These compile silently.
    //  works fine
    std::cout << "getSVfromPerm: \"" << myClass.getSVfromPerm() << "\"." << std::endl;
    //  works fine
    std::cout << "getSVfromRef: \"" << myClass.getSVfromRef() << "\"." << std::endl;
    //  silent bug prints garbage
    std::cout << "getSVfromTemp: \"" << myClass.getSVfromTemp() << "\"." << std::endl;
}

Solution

  • Is there a way to get a compiler warning when returning a by-value string_view from a temporary?

    There is! Use clang 10. For this program:

    #include <string>
    #include <string_view>
    
    struct C
    {
        std::string getS();
        std::string_view getSVfromTemp() { return getS(); }
    };
    

    clang-10 emits:

    <source>:7:47: warning: returning address of local temporary object [-Wreturn-stack-address]
        std::string_view getSVfromTemp() { return getS(); }    
                                                  ^~~~~~