In the following C++ code GCC 14 with -Wall -Wextra
flags produces a possibly dangling reference
warning for function g(), but not f(). Why?
/* getval.h */
#include <string>
std::string const & getVal(std::string const & key);
/* main.cpp */
#include "getval.h"
#include <iostream>
void f()
{
std::string key{"x"};
std::string const &s = getVal(key);
std::cout << "x->" << s << '\n';
}
void g()
{
std::string const &s = getVal("x");
std::cout << "x->" << s << '\n';
}
int main()
{
f();
g();
}
/* getval.cpp */
#include "getval.h"
#include <map>
std::string const & getVal(std::string const & key)
{
static std::map<std::string, std::string> map = [](){
std::map<std::string, std::string> m;
m.emplace("x", "123");
m.emplace("y", "456");
return m;
}();
static std::string empty;
auto it = map.find(key);
return it != map.end() ? it->second : empty;
}
/* Output:
/app/main.cpp: In function 'void g()':
/app/main.cpp:13:22: warning: possibly dangling reference to a temporary [-Wdangling-reference]
13 | std::string const &s = getVal("x");
| ^
/app/main.cpp:13:32: note: the temporary was destroyed at the end of the full expression 'getVal(std::__cxx11::basic_string<char>(((const char*)"x"), std::allocator<char>()))'
13 | std::string const &s = getVal("x");
| ~~~~~~^~~~~
Program returned: 0
x->123
x->123
I would expect it to produce the warning in both cases or none (earlier gcc versions or clang do not produce a warning).
This is known gcc issue. And false positive.
You can
-Wno-dangling-reference
or drop -Wextra
.std::string_view
(this is just like a fancy version of strings const reference):[[nodiscard]] std::string_view getVal(std::string_view key)
{
using namespace std::literals;
static const std::map<std::string_view, std::string_view> map {
{ "x"sv, "123"sv },
{ "y"sv, "456"sv },
};
auto it = map.find(key);
return it != map.end() ? it->second : ""sv;
}
https://godbolt.org/z/P4nxh8nYa
Edit:
Since you prefer use #pragma GCC diagnostic
and you did it incorrectly, here is better way to do it:
// check if problematic warning -Wdangling-reference is available
#if __GNUC__ >= 13
#define GCC_PUSH_DIAGNOSTIC_DISABLE_DANGLING_REF _Pragma("GCC diagnostic push") \
_Pragma("GCC diagnostic ignored \"-Wdangling-reference\"")
#define GCC_DIAGNOSTIC_POP _Pragma("GCC diagnostic pop")
#else
#define GCC_PUSH_DIAGNOSTIC_DISABLE_DANGLING_REF
#define GCC_DIAGNOSTIC_POP
#endif
[[nodiscard]] std::string const& getVal(std::string const& key);
void f()
{
std::string key { "x" };
std::string const& s = getVal(key);
std::cout << "x->" << s << '\n';
}
void g()
{
GCC_PUSH_DIAGNOSTIC_DISABLE_DANGLING_REF
std::string const& s = getVal("x");
GCC_DIAGNOSTIC_POP
std::cout << "x->" << s << '\n';
}