c++ c visual-c++ gcc gcc-warning

c++ - MSVC equivalente de__attribute__((warn_unused_result))?



visual-c++ gcc (5)

Estoy encontrando que __attribute__ ((warn_unused_result)) es muy útil como medio para alentar a los desarrolladores a no ignorar los códigos de error que devuelven las funciones, pero necesito esto para trabajar con MSVC así como con compiladores compatibles con gcc y gcc, como ICC. ¿Los compiladores de Microsoft Visual Studio C / C ++ tienen un mecanismo equivalente? (He intentado vadear a través de MSDN sin suerte hasta ahora.)


ACTUALIZACIÓN PARA MSVC 2012 Y DESPUÉS

Muchas gracias a @Albert por señalar que MSVC ahora admite la anotación _Check_return_ partir de Visual Studio 2012 cuando se usa el análisis de código estático SAL. Estoy agregando esta respuesta para poder incluir una macro multiplataforma que puede ser útil para otros:

#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

Tenga en cuenta que, a diferencia de gcc et al , (a) MSVC requiere anotaciones tanto en la declaración como en la definición de una función, y (b) la anotación debe estar al inicio de la declaración / definición (gcc permite cualquiera). Por lo tanto, el uso normalmente tendrá que ser, por ejemplo:


// foo.h CHECK_RETURN int my_function(void); // declaration


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


Tenga en cuenta también que necesitará el /analyze (o -analyze ) si compila desde la línea de comandos, o su equivalente si usa el IDE de Visual Studio. Esto también tiende a ralentizar un poco la acumulación.


Algunas ediciones de VisualStudio vienen empaquetadas con una herramienta de análisis estático que solía llamarse PREFast (ahora llamado simplemente "Análisis de código para C / C ++"). PREFast utiliza anotaciones para marcar código. Una de esas anotaciones, MustCheck , hace lo que estás buscando.


Creo que la anotación SAL que otros han mencionado es la respuesta correcta para MSVC, pero supongo que algunas personas estarán interesadas en una mayor portabilidad que solo los compatibles con MSVC, GCC y GCC, así que ...

En primer lugar, GCC solo admite warn_unused_result desde 3.4. Es posible que desee verificar los valores de __GNUC__ / __GNUC_MINOR__ lugar de solo verificar si __GNUC__ está definido, aunque en este punto tengo problemas para imaginar que alguien utilice una versión de GCC más antigua que 3.4.

Varios compiladores admiten el atributo de función de estilo GCC, y pueden o no definir __GNUC__ y amigos:

  • Clang (verifique con __has_attribute(warn_unused_result) ), y compiladores basados ​​en él (emscripten, xlc 13+, armclang, etc.), aunque AFAIK siempre se hace pasar por lo menos como GCC 4.2, por lo que probablemente no necesite una verificación explícita.
  • Intel no siempre define __GNUC__ (vea el indicador -no-gcc ). No sé cuándo empezaron a admitirlo (su documentación es muy deficiente), pero sé que 16.0+ es seguro.
  • TI 8.0+ lo soporta
  • TI 7.3+ lo soporta cuando se pasa --gcc; __TI_GNU_ATTRIBUTE_SUPPORT__ se definirá cuando lo sea.
  • Oracle Developer Studio 12.6+ lo admite en modo C ++, aunque no en C.
  • PGI lo soporta en modo C ++. AFAICT no está documentado, así que no estoy seguro de cuándo se agregó (es el número 1650-D), pero definitivamente está presente en 17.10+. Se ignora silenciosamente en modo C, con suerte lo implementarán algún día.

Además, C ++ 17 agrega un atributo [[nodiscard]] . Para las versiones de GCC / clang que admiten [[nodiscard]] en modo C ++ 17 también puedes usar [[gnu::nodiscard]] en C ++ 11 y en el modo mayor, pero si lo [[gnu::nodiscard]] detrás de una macro de todas __attribute__((__warn_unused_result__)) no veo una razón para hacerlo en lugar de usar __attribute__((__warn_unused_result__)) .

Juntándolo, hay una macro HEDLEY_WARN_UNUSED_RESULT en Hedley que se parece a:

#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

Debería poder eliminar las macros internas de Hedley y simplemente copiar la lógica sin demasiados problemas si no desea utilizar Hedley (es de dominio público / CC0). Si decide hacerlo, probablemente debería basar su puerto en la versión del repositorio, ya que es mucho menos probable que recuerde mantener esta respuesta actualizada con nueva información.


Es _Check_return_ . Vea here para ejemplos de anotaciones similares y here para el comportamiento de la función. Es compatible desde MSVC 2012.

Ejemplo:

_Check_return_ int my_return_must_be_checked() { return 42; }


Por lo que yo sé, los compiladores de MS no tienen un pragma o atributo equivalente; la única advertencia de tipo "no utilizado" que puede obtener es para las variables cuando tiene el optimizador activado con el nivel de advertencia adecuado.