Определение встроенной функции с внешней связью, содержащей ссылку на статический объект - PullRequest
1 голос
/ 10 мая 2019

Существует ограничение 6.7.4(p3):

Встроенное определение функции с внешней связью не должно содержать определение модифицируемого объекта со статической или длительностью хранения потока и не должно содержатьссылка на идентификатор с внутренней связью.

Рассмотрим следующий пример:

static const int i = 10;

void do_print(void);

inline void do_print(void){
    printf("%d/n", i); //Reference to an identifier with internal linkage
                       //constraint violation
}

DEMO

Здесь встроенное определениеФункция с внешней связью использует идентификатор с внутренней связью.Таким образом, в соответствии с 5.1.1.3(p1):

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

Я ожидал, что компилятор как-то сообщит о нарушении этого ограничения (некоторые предупреждения).Но код компилируется просто без предупреждений или каких-либо других сообщений.

Вопрос: : Почему диагностическое сообщение не выдается в случае нарушения ограничения, указанного выше?

Ответы [ 2 ]

4 голосов
/ 10 мая 2019

Вопрос : почему диагностическое сообщение не выдается в случае нарушения ограничения, описанного выше?

Поскольку ваш компилятор не соответствует этому.

Вот и все, что нужно сделать.Вы правильно проанализировали текст стандарта и правильно применили его к представленному коду.Соответствующая реализация должна выдавать диагностику ссылки на переменную i встроенной реализацией do_print.Реализация, которая не является, следовательно, несоответствующей.

Я отмечаю на этом этапе, что некоторые компиляторы не соответствуют этому общему способу - исключая требуемую диагностику - по умолчанию, при этом предоставляя возможность длявключение этих обязательных диагностики.Это функция опции -pedantic в GCC, например.Однако я считаю, что моя (несколько устаревшая) версия GCC не предупреждает о вашем коде, даже если указано -pedantic.

4 голосов
/ 10 мая 2019

cppreference содержит параграф, объясняющий обоснование этого:

Если функция объявляется встроенной в некоторых единицах перевода, ее не нужно везде объявлять встроенной: самое большее одна единица перевода может также предоставлять обычную, не встроенную нестатическую функцию или функцию, объявленную extern inline. Эта единица перевода, как говорят, обеспечивает внешнее определение. Одно внешнее определение должно существовать в программе, если в выражении используется имя функции с внешней связью, см. Одно правило определения.

Если в программе существует внешнее определение, адрес функции всегда является адресом внешней функции, но когда этот адрес используется для вызова функции, не указывается, является ли встроенное определение (если оно присутствует в переводе). единица) или внешнее определение называется.

В записке также говорится (подчеркните мою):

Встроенное ключевое слово было взято из C ++, но в C ++, если функция объявляется встроенной, она должна объявляться встроенной в каждой единице перевода, а также каждое определение встроенной функции должно быть точно таким же ( в C, определения могут быть разными, если поведение программы не зависит от различий ). С другой стороны, C ++ допускает неконстантную статическую локальную функцию, и все статические локальные функции из разных определений встроенной функции одинаковы в C ++, но различны в C.

Это означает, что если локальная встроенная функция использует static const value в одной единице перевода, не встроенная функция с тем же именем может быть определена в другой единице перевода с другим значением для статической переменной const, что приводит к явному UB потому что не указано, будет ли компилятор использовать локальную строку в глобальной не встроенной версии.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...