MSVC эквивалент __attribute__ ((warn_unused_result))? - PullRequest
22 голосов
/ 19 ноября 2010

Я нахожу __attribute__ ((warn_unused_result)) очень полезным для поощрения разработчиков не игнорировать коды ошибок, возвращаемые функциями, но мне нужно это для работы с MSVC, а также с gcc и gcc-совместимыми компиляторами, такими как ICC. Имеют ли компиляторы Microsoft Visual Studio C / C ++ эквивалентный механизм? (Я пока безуспешно пробирался через MSDN.)

Ответы [ 5 ]

13 голосов
/ 31 марта 2014

Это _Check_return_.См. здесь для примеров подобных аннотаций и здесь для поведения функции.Поддерживается с MSVC 2012.

Пример:

_Check_return_
int my_return_must_be_checked() {
    return 42;
}
8 голосов
/ 31 марта 2014

ОБНОВЛЕНИЕ ДЛЯ MSVC 2012 И ПОЗЖЕ

Большое спасибо @Albert за то, что MSVC теперь поддерживает аннотацию _Check_return_ в Visual Studio 2012 при использовании статического анализа кода SAL. Я добавляю этот ответ, чтобы добавить кроссплатформенный макрос, который может быть полезен другим:

#if defined(__GNUC__) && (__GNUC__ >= 4)
#define CHECK_RESULT __attribute__ ((warn_unused_result))
#elif defined(_MSC_VER) && (_MSC_VER >= 1700)
#define CHECK_RESULT _Check_return_
#else
#define CHECK_RESULT
#endif

Обратите внимание, что, в отличие от gcc и др. , (a) MSVC требует аннотаций как для определения функции , так и , и (b) аннотация должна быть в начале из объявления / определения (gcc позволяет либо). Таким образом, использование, как правило, должно быть, например .:


// foo.h

CHECK_RETURN int my_function(void); // declaration


// foo.c

CHECK_RETURN int my_function(void)  // definition
{
    return 42;
}


Также обратите внимание, что вам понадобится переключатель /analyze (или -analyze) при компиляции из командной строки или эквивалент при использовании Visual Studio IDE. Это также может несколько замедлить сборку.

5 голосов
/ 19 ноября 2010

Некоторые выпуски VisualStudio поставляются в комплекте с инструментом статического анализа, который раньше назывался PREFast (теперь называется просто «Анализ кода для C / C ++»).PREFast использует аннотации для разметки кода.Одна из этих аннотаций, MustCheck , делает то, что вы ищете.

3 голосов
/ 19 ноября 2010

Насколько мне известно, компиляторы MS не имеют эквивалентной прагмы или атрибута - единственное предупреждение о "неиспользованном" типе, которое вы можете получить, относится к переменным, когда у вас включен оптимизатор с соответствующим уровнем предупреждения.

1 голос
/ 24 марта 2018

Я думаю, что аннотация SAL, о которой упоминали другие, является правильным ответом для MSVC, но я предполагаю, что некоторые люди будут заинтересованы в большей переносимости, чем просто MSVC, GCC и GCC-совместимые компиляторы, поэтому…

Во-первых, GCC поддерживает только warn_unused_result, начиная с 3.4.Вы можете хотеть проверить значения __GNUC__ / __GNUC_MINOR__ вместо того, чтобы просто проверять, определено ли __GNUC__, хотя в этот момент у меня возникают проблемы с представлением кого-либо, использующего версию GCC старше 3.4.

Несколько компиляторов поддерживают атрибут функции в стиле GCC и могут определять или не определять __GNUC__ и друзей:

  • Clang (проверьте с помощью __has_attribute(warn_unused_result)) и компиляторы на основеэто (emscripten, xlc 13+, armclang и т. д.), хотя AFAIK всегда маскируется под как минимум GCC 4.2, поэтому вам, вероятно, не требуется явная проверка.
  • Intel не делаетне всегда определяйте __GNUC__ (см. флаг -no-gcc).Я не знаю, когда они начали поддерживать его (их документации крайне не хватает), но я знаю, что 16.0+ безопасен.
  • TI 8.0+ поддерживает его
  • TI 7.3+ поддерживает его, когда --gcc пройден;__TI_GNU_ATTRIBUTE_SUPPORT__ будет определено, когда оно есть.
  • Oracle Developer Studio 12.6+ поддерживает его в режиме C ++, , но не C .
  • PGI поддерживает его в режиме C ++.AFAICT, он недокументирован, поэтому я не уверен, когда он был добавлен (это # ​​1650-D), но он определенно присутствует в 17.10+.Он тихо игнорируется в режиме C, надеюсь, они когда-нибудь его реализуют.

Кроме того, C ++ 17 добавляет атрибут [[nodiscard]].Для версий GCC / clang, которые поддерживают [[nodiscard]] в режиме C ++ 17, вы также можете использовать [[gnu::nodiscard]] в режиме C ++ 11 и выше, но если вы все равно скрываете его за макросом, я не вижупричина сделать это вместо того, чтобы просто использовать __attribute__((__warn_unused_result__)).

Соединяя его, есть макрос HEDLEY_WARN_UNUSED_RESULT в Хедли , который выглядит следующим образом:

#if defined(__cplusplus) && (__cplusplus >= 201703L)
#  define HEDLEY_WARN_UNUSED_RESULT [[nodiscard]]
#elif \
  HEDLEY_GNUC_HAS_ATTRIBUTE(warn_unused_result,3,4,0) || \
  HEDLEY_INTEL_VERSION_CHECK(16,0,0) || \
  HEDLEY_TI_VERSION_CHECK(8,0,0) || \
  (HEDLEY_TI_VERSION_CHECK(7,3,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
  (HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \
  HEDLEY_PGI_VERSION_CHECK(17,10,0)
#  define HEDLEY_WARN_UNUSED_RESULT __attribute__((__warn_unused_result__))
#elif defined(_Check_return_) /* SAL */
#  define HEDLEY_WARN_UNUSED_RESULT _Check_return_
#else
#  define HEDLEY_WARN_UNUSED_RESULT
#endif

Вы должны быть в состоянии вырезать внутренние макросы Hedley и просто скопировать логику без особых проблем, если не хотите использовать Hedley (это общественное достояние / CC0).Если вы решите сделать это, вам, вероятно, следует основывать свой порт на версии, указанной в репозитории, поскольку я с гораздо меньшей вероятностью не забуду регулярно обновлять этот ответ новой информацией.

...