Если есть [[noreturn]], то почему нет [[always_return]]?

Если есть [[noreturn]] (C2X, n3301), то почему нет [[always_return]]?

Семантика [[always_return]] может быть следующей:

Функция, объявленная с атрибутом [[always_return]], всегда должна возвращаться к вызывающей стороне.

Обоснованием [[always_return]] является подсказка компилятору о необходимости выполнения оптимизации.

Пример (взято из N3128):

extern void g(int x);
int f(int a, int b)
{
    g(b ? 42 : 43);
    return a / b;
}

Компилятор может (оптимистично) предположить, что UB не происходит.

Однако любые (опасные) последствия UB происходят только в том случае, если UB происходит (т.е. присутствует при выполнении на уровне абстрактной машины).

В этом примере g может завершить программу (т. е. не вернуться). Следовательно, насколько я понимаю, компилятор не может сбросить b ? 42 : 43 до 42, потому что на уровне абстрактной машины a / b не может быть выполнен, следовательно, компилятор не может распространять/использовать предположение, что b не равно нулю.

Однако, если g объявлен с [[always_return]], то, насколько я понимаю, компилятор может сбросить b ? 42 : 43 до 42, потому что на уровне абстрактной машины a / b всегда выполняется, следовательно, компилятор может распространять/использовать предположение, что b не равно нулю.


P.S. Тот же вопрос касается [[may_return]].


УПД. Чтобы сбросить b ? 42 : 43 до 42, g нужно не только всегда возвращаться, но и не иметь наблюдаемого поведения (ОБ). Это так, потому что в COB должно произойти до UB. Следовательно, могут потребоваться дополнительные атрибуты: [[observable]], [[noobservable]]. И g может быть объявлен как:

extern [[always_return]] [[noobservable]] void g(int x);
Meta.stackoverflow.com/a/293819/103167
Ben Voigt 27.08.2024 18:40

Потому что никто не подавал такого предложения ... пока!

pmg 27.08.2024 18:47

ИМО, почему бы и нет [probably_return][almost_certainly_return], [no_one_knows_if_it_returns] и т. д. и т. п.

0___________ 27.08.2024 20:34

@pmg Я думал, что, представляя [[noreturn]] WG, я уже подумал о [[always_return]], и, возможно, кто-то из SO знает, почему [[always_return]] не было принято.

pmor 27.08.2024 20:41

«P.S. Тот же вопрос касается [[may_return]]» — это буквально поведение по умолчанию, все функции без аннотаций могут возвращать, а могут и не возвращать. Какую ценность принесет такая аннотация?

StoryTeller - Unslander Monica 27.08.2024 20:43

@0___________ Действительно, вводим «нечеткую логику типа» (т. е. может/может_не/почти_наверняка/и т. д.). атрибуты, возможно, сомнительны. Однако [[always_return]] является противоположностью [[noreturn]] и, возможно, может быть полезным.

pmor 27.08.2024 20:43

@StoryTeller-UnslanderMonica Действительно, спасибо. Поведение по умолчанию не требует специального атрибута.

pmor 27.08.2024 20:47

"в COB должно произойти до UB" - чушь. Если программа использует UB, то все ее поведение не определено. UB не разделен и не упорядочен по отношению к чему-либо еще. «Неопределенный» означает «неопределенный». Никаких требований к такому поведению не предъявляется. Совсем.

John Bollinger 27.08.2024 21:53

@JohnBollinger Цитата из C2X, n3301 (выделено нами): «В частности, все наблюдаемое поведение (5.2.2.4) выглядит так, как указано в этом документе, когда оно происходит перед операцией с неопределенным поведением при выполнении программы».

pmor 27.08.2024 21:58

Ну это новинка, @pmor. Но кроме того, это из примечания, приложенного к определению «неопределенного поведения», и, следовательно, ненормативного. Поэтому я склонен думать, что любые компиляторы, которые уже выполняют оптимизацию, которую, по вашему мнению, следует запретить, вероятно, будут продолжать это делать, и UB продолжит иметь возможность путешествовать во времени.

John Bollinger 27.08.2024 22:13

Кроме того, фраза «OB должна произойти до UB» — это весьма вводящий в заблуждение способ описать содержание этой заметки. Учитывая, что «происходит до» — это определенный термин в спецификации, лучшим вариантом примечания было бы «OB, которое происходит до того, как экземпляр UB проявится, как описано в спецификации». Что по-прежнему ненормативно. «происходит раньше» — это условие, а не следствие.

John Bollinger 27.08.2024 22:25

@JohnBollinger Определение UB относится к конкретному поведению «при использовании…», а не ко всей программе. К вашему сведению: эта заметка является результатом работы исследовательской группы УБ ​​(см. n3128, особенно 1-й абзац «4. Доводы в пользу конкретной интерпретации»). Re: «выполните оптимизацию, которую, по вашему мнению, следует заблокировать»: недоразумение. Я предлагаю разрешить сбрасывание b ? 42 : 43 до 42, если g имеет как [[always_return]], так и [[noobservable]].

pmor 27.08.2024 22:52

@pmor, без недоразумений. Вы предполагаете, что спецификация не допускает оптимизации свертывания, если реализация не может доказать, что функция g() вернется, так что a / b в конечном итоге будет оценена. В противном случае эту оптимизацию необходимо запретить. Я говорю вам, что любые реализации, которые выполняют такую ​​оптимизацию, скорее всего, будут продолжать это делать, хотя невозможно быть уверенным, будет ли a / b действительно оцениваться. Поскольку на практике выполнение может быть прервано в любой момент, ваша логика исключает любую спекулятивную оптимизацию.

John Bollinger 27.08.2024 23:03
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
13
64
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Если есть [[noreturn]] (C2X, n3301), то почему нет [[always_return]]?

В конечном итоге потому, что комитет не увидел (достаточной) ценности в добавлении такого атрибута. Я склонен предположить, что они не увидели в этом смысла, потому что это даже не было предложено, а если оно было предложено, то оно было отклонено. Конечно, предложение добавить [[noreturn]] не предполагало [[always_return]].

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

И какая польза от этого? При отсутствии какого-либо атрибута и/или специальных знаний о конкретных функциях реализация C должна предполагать, что вызовы функций вернутся. Но даже если обещание [[always_return]] действительно может быть выполнено, эта информация бесполезна для реализации. Это все равно, что я утверждаю, что завтра взойдет солнце. Даже если предположить, что вы абсолютно доверяете мне на этом основании, сделали бы вы что-нибудь другое? Нет, потому что в какой-то степени это имеет значение, вы уже приняли это как рабочее предположение.

[[noreturn]] это другое. Он обеспечивает повышение производительности и улучшенную диагностику по сравнению с неотмеченными функциями, которые по своей конструкции не возвращаются.

Кроме того, атрибут [[noreturn]] является альтернативой спецификатору функции _Noreturn, который присутствует в C начиная с C11, поэтому на самом деле это не новая функция. Переключение на атрибут вместо спецификатора поддерживает гармонизацию с C++. Не существует спецификатора функции, аналогичного вашему гипотетическому [[always_return]].

Посмотрите мой UPD (в конце вопроса). Комбинация [[always_return]] и [[noobservable]] (возможно, может быть объединена в один атрибут) позволит реализации C выполнять оптимизацию на основе (оптимистического) предположения, что UB не происходит (в сочетании со знанием того, что функция всегда возвращает результат и не содержит OB ), что потенциально приведет к увеличению производительности.

pmor 27.08.2024 21:48

Извините, @pmor, нет, я не буду рассматривать изменения, внесенные в вопрос после публикации этого ответа. И если вы считаете, что эти изменения имеют значение, то вам следует знать, что лучше не вносить их в данных обстоятельствах.

John Bollinger 27.08.2024 21:50

Другие вопросы по теме