Если есть [[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);
Потому что никто не подавал такого предложения ... пока!
ИМО, почему бы и нет [probably_return][almost_certainly_return], [no_one_knows_if_it_returns] и т. д. и т. п.
@pmg Я думал, что, представляя [[noreturn]] WG, я уже подумал о [[always_return]], и, возможно, кто-то из SO знает, почему [[always_return]] не было принято.
«P.S. Тот же вопрос касается [[may_return]]» — это буквально поведение по умолчанию, все функции без аннотаций могут возвращать, а могут и не возвращать. Какую ценность принесет такая аннотация?
@0___________ Действительно, вводим «нечеткую логику типа» (т. е. может/может_не/почти_наверняка/и т. д.). атрибуты, возможно, сомнительны. Однако [[always_return]] является противоположностью [[noreturn]] и, возможно, может быть полезным.
@StoryTeller-UnslanderMonica Действительно, спасибо. Поведение по умолчанию не требует специального атрибута.
"в COB должно произойти до UB" - чушь. Если программа использует UB, то все ее поведение не определено. UB не разделен и не упорядочен по отношению к чему-либо еще. «Неопределенный» означает «неопределенный». Никаких требований к такому поведению не предъявляется. Совсем.
@JohnBollinger Цитата из C2X, n3301 (выделено нами): «В частности, все наблюдаемое поведение (5.2.2.4) выглядит так, как указано в этом документе, когда оно происходит перед операцией с неопределенным поведением при выполнении программы».
Ну это новинка, @pmor. Но кроме того, это из примечания, приложенного к определению «неопределенного поведения», и, следовательно, ненормативного. Поэтому я склонен думать, что любые компиляторы, которые уже выполняют оптимизацию, которую, по вашему мнению, следует запретить, вероятно, будут продолжать это делать, и UB продолжит иметь возможность путешествовать во времени.
Кроме того, фраза «OB должна произойти до UB» — это весьма вводящий в заблуждение способ описать содержание этой заметки. Учитывая, что «происходит до» — это определенный термин в спецификации, лучшим вариантом примечания было бы «OB, которое происходит до того, как экземпляр UB проявится, как описано в спецификации». Что по-прежнему ненормативно. «происходит раньше» — это условие, а не следствие.
@JohnBollinger Определение UB относится к конкретному поведению «при использовании…», а не ко всей программе. К вашему сведению: эта заметка является результатом работы исследовательской группы УБ (см. n3128, особенно 1-й абзац «4. Доводы в пользу конкретной интерпретации»). Re: «выполните оптимизацию, которую, по вашему мнению, следует заблокировать»: недоразумение. Я предлагаю разрешить сбрасывание b ? 42 : 43 до 42, если g имеет как [[always_return]], так и [[noobservable]].
@pmor, без недоразумений. Вы предполагаете, что спецификация не допускает оптимизации свертывания, если реализация не может доказать, что функция g() вернется, так что a / b в конечном итоге будет оценена. В противном случае эту оптимизацию необходимо запретить. Я говорю вам, что любые реализации, которые выполняют такую оптимизацию, скорее всего, будут продолжать это делать, хотя невозможно быть уверенным, будет ли a / b действительно оцениваться. Поскольку на практике выполнение может быть прервано в любой момент, ваша логика исключает любую спекулятивную оптимизацию.





Если есть
[[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, нет, я не буду рассматривать изменения, внесенные в вопрос после публикации этого ответа. И если вы считаете, что эти изменения имеют значение, то вам следует знать, что лучше не вносить их в данных обстоятельствах.