Почему устаревшие предупреждения C печатаются дважды?

#c #gcc #g

#c #gcc #g

Вопрос:

Если у меня есть

 namespace foo {
    inline int bar() {
        return 1119;
    }
}

__attribute__((deprecated)) inline int bar() {
    return 138;
}
  

в header.h и

 #include "header.h"
#include <iostream>

int main() {
    int x = bar();
    int y = foo::bar();
    std::cout << x << std::endl;
    std::cout << y << std::endl;
}
  

в source.cpp , затем

 g   source.cpp -o deprecated-test
  

приводит к

 source.cpp: In function ‘int main()’:
source.cpp:5:17: warning: ‘int bar()’ is deprecated [-Wdeprecated-declarations]
     int x = bar();
                 ^
In file included from source.cpp:1:
header.h:7:40: note: declared here
 __attribute__((deprecated)) int bar() {
                                 ^~~
source.cpp:5:17: warning: ‘int bar()’ is deprecated [-Wdeprecated-declarations]
     int x = bar();
                 ^
In file included from source.cpp:1:
header.h:7:40: note: declared here
 __attribute__((deprecated)) int bar() {
  

(в Ubuntu 18.10 с g 8.2.0).

Почему устаревшее предупреждение печатается дважды?

Отбрасываю некоторые предложения, которые были бы бесполезны:

  • [[deprecated]] : Я знаю, что с C 14 вы можете использовать [[deprecated]] атрибут, но мне нужно работать с C 11.

  • Декларация против определения: документы, похоже, подразумевают, что его следует использовать с объявлением функции, а не с определением, но

    1. Мне нужно определить функции inline в заголовке, а не объявлять в заголовке и определять в исходных файлах; и
    2. Попытка такого подхода все равно не остановила печать предупреждения дважды.

Комментарии:

1. Может быть ошибка. Clang не печатает два предупреждения. [[deprecated]] выдает те же результаты (два предупреждения в gcc, одно в clang).

2. @tkausl спасибо, приятно знать! Поскольку clang не выводит предупреждение дважды, мне, возможно, придется попробовать и другие g версии, чтобы узнать, не является ли это недавно введенной и / или недавно исправленной ошибкой

3. версии gcc до 5.5 даже печатают три предупреждения… Интересно. godbolt.org/z/383Hl0

4. @tkausl Вау… Кроме того, спасибо, что указали мне на godbolt.org ресурс. Я видел это раньше, но забыл об этом и не подумал заглянуть туда, чтобы попробовать другие компиляторы

5. @tkausl Похоже, что только gcc 5.x печатает 3 предупреждения. gcc 7.x печатает одно предупреждение, все остальные (которые я проверил) печатают два предупреждения. При использовании адреса устаревшей функции выводятся два предупреждения с помощью gcc 5.x и одно предупреждение для всех других версий.

Ответ №1:

Согласно документации GCC 8.2.0:

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

Должно быть только одно предупреждение, а не два. Итак, это ошибка в GCC.

Существует связанная ошибка для атрибутов типа (а не атрибутов функций) под названием: C / C __attribute__((deprecated)) , похоже, не переносит объявления, как подразумевается в документе.

Это было подтверждено как ошибка.

Комментарии:

1. Это, безусловно, ошибка в GCC, а не проблема с моим кодом, как упоминаете вы (и другие в комментариях к сообщению). Связанная ошибка, о которой вы упомянули, интересна, поскольку они не получают несколько предупреждений при одном использовании, а скорее предупреждения о объявлениях, которые не используются. Похоже, мне нужно будет отправить отдельный отчет об ошибке. Спасибо!