Russian Qt Forum

Компиляторы и платформы => Компиляторы => Тема начата: Гурман от Октябрь 23, 2019, 13:21



Название: Странность с Clang.
Отправлено: Гурман от Октябрь 23, 2019, 13:21
Недавно перевёл свои проекты для Android для Clang - теперь им Qt5 собирается. В проекте была ошибка

Код:
void SettingsDlg::isCalendar(bool goodName)
{
    ui->calendarName->setStyleSheet( goodName ? stylegood : stylebad );
}

bool SettingsDlg::isCalendar(QString accountName)
{
    isCalendar( _checkforname(QString) );
}

и вызов выше был:
    isCalendar( oldname );

То есть у второго варианта функции не было возвращаемого значения, хотя функция объявлена как bool (и в .h также). Компилятор выдал предупреждение, хотя по идее должна выдаваться ошибка - возвращаемое значение не определено. Даже QtCreator 5.10 отметил строку замечанием. Но самое странное, что в таком случае... происходило падение при выходе из второго варианта. Заменил возврат bool на void - всё стало нормально. Ну предупреждение вместо ошибки - это ещё ладно, хотя IMHO должна быть серьёзная ошибка. Но падать то от чего? Возврат ведь не использовался. Неопределённое булево значение легло на стек - false или true, не известно. Но его значение вызывающая функция проигнорировала, указатель стека просто отсчитала на 1 больше, и всё.

Пересмотрел ещё раз код - других косяков не видно, работает как вкопанный. То есть, вторичной наведённой ошибки тоже вроде не было. Да и как она может быть, это же не переменная не инициализированная - одно слово на стеке.


Название: Re: Странность с Clang.
Отправлено: Old от Октябрь 23, 2019, 20:01
Гурман, посмотрите на то, что генерирует clang:
https://godbolt.org/z/9be4e7

Код
C++ (Qt)
#include <cstdint>
 
int a = 0;
 
void test0()
{
   a = 1;
}
 
bool test()
{
   test0();
}
 
int main()
{
   test();
}
 

Если отключить оптимизацию, то на том месте где должен был быть return clang генерирует инструкцию ud2 (https://www.felixcloutier.com/x86/ud).
Код
ASM
test0():                              # @test0()
       push    rbp
       mov     rbp, rsp
       mov     dword ptr [a], 1
       pop     rbp
       ret
test():                               # @test()
       push    rbp
       mov     rbp, rsp
       call    test0()
       ud2
main:                                   # @main
       push    rbp
       mov     rbp, rsp
       sub     rsp, 16
       call    test()
       xor     ecx, ecx
       mov     byte ptr [rbp - 1], al  # 1-byte Spill
       mov     eax, ecx
       add     rsp, 16
       pop     rbp
       ret
a:
       .long   0                       # 0x0
 

А если включить -O1, то вообще вот так:
Код
ASM
test0():                              # @test0()
       mov     dword ptr [rip + a], 1
       ret
test():                               # @test()
       push    rax
       call    test0()
main:                                   # @main
       push    rax
       call    test()
a:
       .long   0                       # 0x0
 

И что там за test выполняется ему не важно. :)


Название: Re: Странность с Clang.
Отправлено: Гурман от Октябрь 23, 2019, 23:31
 :o

я хотел в код глянуть, но некогда было

однако баг репортом запахло...


Название: Re: Странность с Clang.
Отправлено: Old от Октябрь 24, 2019, 06:14
однако баг репортом запахло...
По стандарту эта ситуация приводит к UB.
Хотели неопределенности - нате. :)

Но по человечески конечно разработчики clang козлы. Не хотите/можете генерировать дальше код - выдайте ошибку, а так и ошибку не выдаем и код не генерим. "Вы либо крестик снимите, либо трусы наденьте". :)

gcc тоже варнинг выдает, но хоть код рабочий генерит.


Название: Re: Странность с Clang.
Отправлено: Гурман от Октябрь 24, 2019, 10:31
однако баг репортом запахло...
По стандарту эта ситуация приводит к UB.
Хотели неопределенности - нате. :)
Не.... неопределённость в возвращаемом значении. Но не в алгоритме. По алгоритму функция завершилась, должен быть возврат без определённого значения функции. Обязан быть ret после разбора закрывающей фигурной скобки. Но его нет. Это баг.


Название: Re: Странность с Clang.
Отправлено: Авварон от Октябрь 24, 2019, 11:27
Это баг.

Нет, баг у вас ;)

http://blog.llvm.org/2011/05/what-every-c-programmer-should-know.html


Название: Re: Странность с Clang.
Отправлено: Гурман от Октябрь 24, 2019, 13:23
Это баг.

Нет, баг у вас ;)

http://blog.llvm.org/2011/05/what-every-c-programmer-should-know.html

Мой баг только в отсутствии return. Но это совсем не undefined behaviour. Behaviour как раз defined - завершился блок, составляющий тело функции. Значит завершилась функция, и из неё должен быть возврат. Только значение не определено - undefined value но не behaviour. Во всяком случае именно так работали все 6-7 компиляторов, которыми я когда-либо пользовался, начиная с K&R C в RT-11. Если там в статье написано что-то другое - значит чушь написана.


Название: Re: Странность с Clang.
Отправлено: Авварон от Октябрь 24, 2019, 13:43
Мой баг только в отсутствии return. Но это совсем не undefined behaviour.

Это УБ с точки зрения стандарта. И кланг такой умничка что вставляет трап в месте UB (то, что Old запостил с -O0) чтобы вы могли найти и исправить UB. Гцц даже этого не делает.

Если там в статье написано что-то другое - значит чушь написана.

Не читал, но осуждаю, ясно-понятно.


Название: Re: Странность с Clang.
Отправлено: Igors от Октябрь 24, 2019, 13:51
Во всяком случае именно так работали все 6-7 компиляторов, которыми я когда-либо пользовался,
Ну значит 8-й делает не так, и "стоны придавленного дерева" ничего не изменят


Название: Re: Странность с Clang.
Отправлено: Гурман от Октябрь 24, 2019, 14:51
Clang был бы умничкой, если бы красную ошибку выдал. Как в случае с return; без значения. Поскольку по сути - это именно он и есть.


Название: Re: Странность с Clang.
Отправлено: Авварон от Октябрь 24, 2019, 14:54
Clang был бы умничкой, если бы красную ошибку выдал.


-Wall -Wextra -Wpedantic -Werror


Название: Re: Странность с Clang.
Отправлено: Авварон от Октябрь 24, 2019, 15:05
-Wall (https://clang.llvm.org/docs/DiagnosticsReference.html#wall)-> -Wmost (https://clang.llvm.org/docs/DiagnosticsReference.html#wmost) -> -Wreturn-type (https://clang.llvm.org/docs/DiagnosticsReference.html#wreturn-type)

У чувачка банальный -Wall не включен а виноват кланг лол


Название: Re: Странность с Clang.
Отправлено: Гурман от Октябрь 24, 2019, 15:26
У чувачка банальный -Wall не включен а виноват кланг лол

Тогда этот "чувачок" в Qt Team работает. Потому как я лично просто стал использовать ровно то, что приехало с Qt 5.12.5, без изменений.


Название: Re: Странность с Clang.
Отправлено: qate от Октябрь 25, 2019, 10:57
Это УБ с точки зрения стандарта.

можно ссылку, для ликбеза, на стандарт по УБ для данного случая ?


Название: Re: Странность с Clang.
Отправлено: Авварон от Октябрь 25, 2019, 11:48
можно ссылку, для ликбеза, на стандарт по УБ для данного случая ?

У меня не открывается (http://secdns.dk/blocked?h=www.open-std.org&z=www.open-std.org&u=%2Fjtc1%2Fsc22%2Fwg21%2Fdocs%2Fpapers%2F2017%2Fn4659.pdf#subsection.9.6.3) на работе, но говорят там такое написано.
Код:
Flowing off the end of a constructor, a destructor, or a function with a cv void return type is equivalent to a return with no operand. Otherwise, flowing off the end of a function other than main (6.6.1) results in undefined behavior.


Название: Re: Странность с Clang.
Отправлено: ViTech от Октябрь 25, 2019, 12:15
можно ссылку, для ликбеза, на стандарт по УБ для данного случая ?

В разных стандартах формулировки незначительно отличаются. В текущем черновике (http://eel.is/c++draft/stmt.return) вот так написано:
Цитировать
Flowing off the end of a constructor, a destructor, or a non-coroutine function with a cv void return type is equivalent to a return with no operand. Otherwise, flowing off the end of a function other than main or a coroutine ([dcl.fct.def.coroutine]) results in undefined behavior.

И вот тут (http://eel.is/c++draft/diff.stat#2) ещё:
Цитировать
Change: It is now invalid to return (explicitly or implicitly) from a function which is declared to return a value without actually returning a value.

Rationale: The caller and callee may assume fairly elaborate return-value mechanisms for the return of class objects. If some flow paths execute a return without specifying any value, the implementation must embody many more complications. Besides, promising to return a value of a given type, and then not returning such a value, has always been recognized to be a questionable practice, tolerated only because very-old C had no distinction between void functions and int functions.

А также можно почитать: Why does flowing off the end of a non-void function without returning a value not produce a compiler error? (https://stackoverflow.com/questions/1610030/why-does-flowing-off-the-end-of-a-non-void-function-without-returning-a-value-no).


Название: Re: Странность с Clang.
Отправлено: ViTech от Октябрь 25, 2019, 12:44
Тогда этот "чувачок" в Qt Team работает. Потому как я лично просто стал использовать ровно то, что приехало с Qt 5.12.5, без изменений.

Можно ссылку, где в Qt такое непотребство?


Название: Re: Странность с Clang.
Отправлено: kambala от Октябрь 25, 2019, 16:49
clang из Xcode по умолчанию выдает предупреждения -Wreturn-type, например. у меня никаких нестандартных настроек в креаторе и проекте нет.


Название: Re: Странность с Clang.
Отправлено: Гурман от Октябрь 26, 2019, 00:59
говорят там такое написано.
Код:
Flowing off the end of a constructor, a destructor, or a function with a cv void return type is equivalent to a return with no operand. Otherwise, flowing off the end of a function other than main (6.6.1) results in undefined behavior.
И это есть бред, который K&R идеологии противоречит, и не имеет силы поэтому.


Название: Re: Странность с Clang.
Отправлено: Авварон от Октябрь 26, 2019, 14:01
И это есть бред, который K&R идеологии противоречит, и не имеет силы поэтому.

У К&Р не было классов и можно было возвращать 0. А что возвращать в плюсах? Дефол-констрактед Т? А если дефолт ктора нет? Вот вам и УБ что определить поведение по умолчанию невозможно.
Как выше уже написали, можно написать такую функцию, которая будет иметь ветку без return, но которая никогда не выполнится (и анализатор хрен докажет что эта ветка не выполняется) => всё отлично, функция абсолютно валидная с тз языка и юзкейзов и никакого УБ.


Название: Re: Странность с Clang.
Отправлено: Гурман от Октябрь 26, 2019, 18:28
Тогда этот "чувачок" в Qt Team работает. Потому как я лично просто стал использовать ровно то, что приехало с Qt 5.12.5, без изменений.

Можно ссылку, где в Qt такое непотребство?
Ссылочку на что? На дистрибутив Qt для установки?


Название: Re: Странность с Clang.
Отправлено: Гурман от Октябрь 26, 2019, 18:31
У К&Р не было классов и можно было возвращать 0. А что возвращать в плюсах?
То же самое, что и без плюсов. Функция описана как возвращающая bool. Классы тут ни при чём, этот тип по-умолчанию обычный скалярный, такой же как у K&R.


Название: Re: Странность с Clang.
Отправлено: ViTech от Октябрь 26, 2019, 19:36
Можно ссылку, где в Qt такое непотребство?
Ссылочку на что? На дистрибутив Qt для установки?

Весь дистрибутив Qt - сплошное непотребство? :o У меня, конечно, были подозрения, но не такого масштаба.

То есть у второго варианта функции не было возвращаемого значения, хотя функция объявлена как bool (и в .h также). Компилятор выдал предупреждение, хотя по идее должна выдаваться ошибка - возвращаемое значение не определено. Даже QtCreator 5.10 отметил строку замечанием.
Мой баг только в отсутствии return.
Тогда этот "чувачок" в Qt Team работает. Потому как я лично просто стал использовать ровно то, что приехало с Qt 5.12.5, без изменений.

Так баг у вас или у чувачка из Qt Team?


Название: Re: Странность с Clang.
Отправлено: kuzulis от Октябрь 26, 2019, 20:48
Цитировать
Так баг у вас или у чувачка из Qt Team?

Наврятли это из Qt-team, слишком уж код-стайл не тот.  ::)


Название: Re: Странность с Clang.
Отправлено: Гурман от Октябрь 26, 2019, 21:59
Так баг у вас или у чувачка из Qt Team?

Чтобы не терять смысл написанного другими, и не задавать глупые вопросы, надо внимательнее читать реплики.


Название: Re: Странность с Clang.
Отправлено: ViTech от Октябрь 27, 2019, 10:42
Чтобы не терять смысл написанного другими, и не задавать глупые вопросы, надо внимательнее читать реплики.

Действительно, я было подумал, что из-за опции компилятора, где-то в Qt пропустили функцию без return. Оказывается, всё намного проще. Вопрос про непотребства в Qt снимается.

У чувачка банальный -Wall не включен а виноват кланг лол

Тогда этот "чувачок" в Qt Team работает. Потому как я лично просто стал использовать ровно то, что приехало с Qt 5.12.5, без изменений.

Т.е. какие опции компилятора в Qt  Team выставят, с такими вы проекты и собираете. Сами эти опции не контролируете, и задать другие, без чувачка из Qt  Team, не можете.


Название: Re: Странность с Clang.
Отправлено: Гурман от Октябрь 27, 2019, 11:41
Т.е. какие опции компилятора в Qt  Team выставят, с такими вы проекты и собираете. Сами эти опции не контролируете, и задать другие, без чувачка из Qt  Team, не можете.
Могу. Но ещё я 11 лет езжу на машине марки Ford, и ни разу не перепрограммировал её управление двигателем и коробкой передач. Хотя тоже могу.


Название: Re: Странность с Clang.
Отправлено: _Bers от Январь 28, 2022, 04:22
можно ссылку, для ликбеза, на стандарт по УБ для данного случая ?

http://eel.is/c++draft/stmt.return#4

Цитировать
Flowing off the end of a constructor, a destructor, or a non-coroutine function with a cv void return type is equivalent to a return with no operand.
Otherwise, flowing off the end of a function other than main or a coroutine ([dcl.fct.def.coroutine]) results in undefined behavior.