Неожиданное предупреждение gcc: функция возвращает адрес локальной переменной — ошибка компилятора?

Ниже приведен минимальный рабочий пример (хорошо, на самом деле это минимальный нерабочий пример :-)). При компиляции с помощью gcc (с версии 5.0 до 9.3) выдается следующее предупреждение. Кажется, даже предупреждение выдается только в релизной сборке (-02 и выше).

Код:

class A
{
};

class B
{
    const A& getA() const
    {
        static A a;
        return a;
    }
    const A& get(bool b) const; 
};

const A& B::get(bool b) const
{
    return static_cast<const A&>(b ? getA() : getA());
}

int main(int argc, char** argv)
{
    return 0;
}

Вывод компилятора:

<source>: In member function 'const A& B::get(bool) const':
<source>:17:50: warning: function returns address of local variable [-Wreturn-local-addr]
  return static_cast<const A&>(b ? getA() : getA());
<source>:17:50: note: declared here
  return static_cast<const A&>(b ? getA() : getA());
Compiler returned: 0

Приведенный выше код нормально компилируется как с MSVC, так и с clang, и даже с gcc 10.1. Он также нормально компилируется в режиме отладки (с -O1 или -O0) со старыми версиями gcc.

Вы видите что-то неправильное в коде, или это действительно проблема компилятора?

Наблюдение

Когда я добавляю конструктор удаленной копии в класс A (A(const A&) = delete;), предупреждение исчезает, и компилятор останавливается для создания локальной переменной.

Попробуйте Вы можете попробовать gcc.godbolt.org


person Mi-La    schedule 11.06.2020    source источник
comment
Зачем использовать gcc для С++?   -  person David G. Pickett    schedule 11.06.2020
comment
@DavidG.Pickett Почему бы и нет?   -  person eerorika    schedule 11.06.2020
comment
Похоже, это ложное срабатывание предупреждения. И похоже, это уже исправлено в gcc 10.   -  person eerorika    schedule 11.06.2020
comment
@eerorika Это не ложное срабатывание, если вы посмотрите на сгенерированный код, он неверен. Даже с -O0 сгенерированный код возвращает недопустимую ссылку.   -  person IlCapitano    schedule 11.06.2020
comment
Если вы удалите static_cast, похоже, это будет ожидаемое поведение.   -  person IlCapitano    schedule 11.06.2020
comment
@IlCapitano Если сгенерированный код тоже неверен, то это гораздо более серьезная ошибка в компиляторе, чем просто неработающее предупреждение.   -  person eerorika    schedule 11.06.2020
comment
@IlCapitano Верно. На самом деле, именно так мы решили нашу настоящую проблему. Проблема возникла в сгенерированном коде, и неясно, почему static_cast должна вызывать какие-либо проблемы:/.   -  person Mi-La    schedule 11.06.2020
comment
Это исправлено в GCC10. Если вы посмотрите, как разрабатывается GCC, с исправлениями ошибок, которые сначала вносятся в основную ветку, а затем когда-то выбирают вишню для выпуска ветки... Я полагаю, что более консервативно использовать самую последнюю версию GCC.   -  person Oliv    schedule 11.06.2020
comment
@Oliv Так это действительно была ошибка gcc? Я просто хотел убедиться, что код правильный. Можете ли вы найти правильную ошибку в gcc bugzilla. Bugzilla, кажется, гораздо более глючная, чем gcc (по крайней мере, ее поиск), поэтому я не могу ничего там найти :-).   -  person Mi-La    schedule 11.06.2020
comment
Пока я нашел это: gcc.gnu.org/bugzilla/show_bug. cgi?id=67795. Кажется, связанная проблема. Также интересно, что это происходит только с static_cast. Когда вы используете reinterpret_cast, const_cast или приведение в стиле c, все работает правильно. Я думал, что приведение в стиле c должно выполнять const_cast или static_cast C++???   -  person Mi-La    schedule 11.06.2020
comment
Да, приведение в стиле c эквивалентно static_cast, если static_cast не имеет неправильного формата. Тот факт, что GCC не создает тот же самый код с приведением в стиле c, является еще одним доказательством того, что GCC содержит ошибки.   -  person Oliv    schedule 11.06.2020