Tôi biết câu hỏi là về GCC, nhưng đối với những người đang tìm kiếm cách thực hiện điều này trong các trình biên dịch khác và / hoặc nhiều
TL; DR
Bạn có thể muốn xem Hedley , một tiêu đề C / C ++ đơn lẻ trong miền công cộng mà tôi đã viết rất nhiều thứ này cho bạn. Tôi sẽ đặt một phần nhanh về cách sử dụng Hedley cho tất cả điều này ở cuối bài này.
Vô hiệu hóa cảnh báo
#pragma warning (disable: …)
có tương đương trong hầu hết các trình biên dịch:
- MSVC:
#pragma warning(disable:4996)
- GCC:
#pragma GCC diagnostic ignored "-W…"
trong đó dấu chấm lửng là tên của cảnh báo;ví dụ như , #pragma GCC diagnostic ignored "-Wdeprecated-declarations
.
- kêu vang :
#pragma clang diagnostic ignored "-W…"
. Cú pháp về cơ bản giống như của GCC và nhiều tên cảnh báo giống nhau (mặc dù nhiều tên không).
- Trình biên dịch Intel C: Sử dụng cú pháp MSVC, nhưng hãy nhớ rằng các số cảnh báo là hoàn toàn khác nhau. Thí dụ:
#pragma warning(disable:1478 1786)
.
- PGI: Có một
diag_suppress
pragma:#pragma diag_suppress 1215,1444
- TI: Có một
diag_suppress
pragma có cùng cú pháp (nhưng các số cảnh báo khác nhau!) Như PGI:pragma diag_suppress 1291,1718
- Oracle Developer Studio (suncc): có một
error_messages
pragma. Khó chịu, các cảnh báo là khác nhau đối với trình biên dịch C và C ++. Cả hai đều vô hiệu hóa cùng một cảnh báo:
- C:
#pragma error_messages(off,E_DEPRECATED_ATT,E_DEPRECATED_ATT_MESS)
- C ++:
#pragma error_messages(off,symdeprecated,symdeprecated2)
- IAR: cũng sử dụng
diag_suppress
như PGI và TI, nhưng cú pháp thì khác. Một số số cảnh báo là như nhau, nhưng những số khác tôi đã chuyển hướng:#pragma diag_suppress=Pe1444,Pe1215
- Pelles C: tương tự như MSVC, mặc dù các số khác nhau
#pragma warn(disable:2241)
Đối với hầu hết các trình biên dịch, thường nên kiểm tra phiên bản trình biên dịch trước khi thử tắt nó, nếu không, bạn sẽ chỉ kích hoạt một cảnh báo khác. Ví dụ: GCC 7 đã thêm hỗ trợ cho -Wimplicit-fallthrough
cảnh báo, vì vậy nếu bạn quan tâm đến GCC trước 7, bạn nên làm gì đó như
#if defined(__GNUC__) && (__GNUC__ >= 7)
# pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
#endif
Đối với clang và trình biên dịch dựa trên clang, chẳng hạn như các phiên bản XL C / C ++ và armclang mới hơn, bạn có thể kiểm tra xem trình biên dịch có biết về một cảnh báo cụ thể bằng cách sử dụng __has_warning()
macro không.
#if __has_warning("-Wimplicit-fallthrough")
# pragma clang diagnostic ignored "-Wimplicit-fallthrough"
#endif
Tất nhiên bạn cũng phải kiểm tra xem __has_warning()
macro có tồn tại không:
#if defined(__has_warning)
# if __has_warning("-Wimplicit-fallthrough")
# pragma clang diagnostic ignored "-Wimplicit-fallthrough"
# endif
#endif
Bạn có thể bị cám dỗ để làm một cái gì đó như
#if !defined(__has_warning)
# define __has_warning(warning)
#endif
Vì vậy, bạn có thể sử dụng __has_warning
một chút dễ dàng hơn. Clang thậm chí còn gợi ý một cái gì đó tương tự cho __has_builtin()
macro trong hướng dẫn của họ. Đừng làm điều này . Các mã khác có thể kiểm tra __has_warning
và quay lại kiểm tra các phiên bản trình biên dịch nếu nó không tồn tại và nếu bạn xác định __has_warning
bạn sẽ phá vỡ mã của chúng. Cách đúng đắn để làm điều này là tạo một macro trong không gian tên của bạn. Ví dụ:
#if defined(__has_warning)
# define MY_HAS_WARNING(warning) __has_warning(warning)
#else
# define MY_HAS_WARNING(warning) (0)
#endif
Sau đó, bạn có thể làm những thứ như
#if MY_HAS_WARNING(warning)
# pragma clang diagnostic ignored "-Wimplicit-fallthrough"
#elif defined(__GNUC__) && (__GNUC__ >= 7)
# pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
#endif
Đẩy và bật
Nhiều trình biên dịch cũng hỗ trợ một cách để đẩy và bật các cảnh báo lên ngăn xếp. Ví dụ: điều này sẽ vô hiệu hóa cảnh báo trên GCC cho một dòng mã, sau đó đưa nó trở về trạng thái trước đó:
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated"
call_deprecated_function();
#pragma GCC diagnostic pop
Tất nhiên, không có nhiều thỏa thuận giữa các trình biên dịch về cú pháp:
- GCC 4.6+:
#pragma GCC diagnostic push
/#pragma GCC diagnostic pop
- tiếng kêu:
#pragma clang diagnostic push
/#pragma diagnostic pop
- Intel 13+ (và có thể sớm hơn):
#pragma warning(push)
/#pragma warning(pop)
- MSVC 15+ (VS 9.0 / 2008):
#pragma warning(push)
/#pragma warning(pop)
- ARM 5.6+:
#pragma push
/#pragma pop
- TI 8.1+:
#pragma diag_push
/#pragma diag_pop
- Pelles C 2.90+ (và có thể sớm hơn):
#pragma warning(push)
/#pragma warning(pop)
Nếu bộ nhớ phục vụ, đối với một số phiên bản GCC rất cũ (như 3.x, IIRC), các pragma đẩy / pop phải nằm ngoài chức năng.
Ẩn các thông tin chi tiết
Đối với hầu hết các trình biên dịch, có thể ẩn logic đằng sau các macro sử dụng _Pragma
, được giới thiệu trong C99. Ngay cả trong chế độ không C99, hầu hết các trình biên dịch đều hỗ trợ _Pragma
; ngoại lệ lớn là MSVC, có __pragma
từ khóa riêng với một cú pháp khác. Tiêu chuẩn _Pragma
có một chuỗi, phiên bản của Microsoft không:
#if defined(_MSC_VER)
# define PRAGMA_FOO __pragma(foo)
#else
# define PRAGMA_FOO _Pragma("foo")
#endif
PRAGMA_FOO
Gần tương đương, một khi được xử lý trước, để
#pragma foo
Điều này cho phép chúng tôi tạo các macro để chúng tôi có thể viết mã như
MY_DIAGNOSTIC_PUSH
MY_DIAGNOSTIC_DISABLE_DEPRECATED
call_deprecated_function();
MY_DIAGNOSTIC_POP
Và ẩn đi tất cả các kiểm tra phiên bản xấu xí trong các định nghĩa vĩ mô.
Cách dễ dàng: Hedley
Bây giờ bạn đã hiểu các cơ chế về cách làm những thứ như thế này một cách hợp lý trong khi giữ cho mã của bạn sạch sẽ, bạn hiểu một trong những dự án của tôi, Hedley làm gì. Thay vì đào qua hàng tấn tài liệu và / hoặc cài đặt nhiều phiên bản của nhiều trình biên dịch nhất có thể để kiểm tra, bạn chỉ có thể bao gồm Hedley (đây là một tiêu đề C / C ++ công khai duy nhất) và được thực hiện với nó. Ví dụ:
#include "hedley.h"
HEDLEY_DIAGNOSTIC_PUSH
HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
call_deprecated();
HEDLEY_DIAGNOSTIC_POP
Sẽ vô hiệu hóa cảnh báo về việc gọi một chức năng không dùng nữa trên GCC, clang, ICC, PGI, MSVC, TI, IAR, ODS, Pelles và có thể những người khác (tôi có lẽ sẽ không cập nhật câu trả lời này khi tôi cập nhật Hedley). Và, trên các trình biên dịch không được biết là hoạt động, các macro sẽ được xử lý trước thành không có gì, vì vậy mã của bạn sẽ tiếp tục hoạt động với bất kỳ trình biên dịch nào. Tất nhiên đó HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
không phải là cảnh báo duy nhất mà Hedley biết, cũng như vô hiệu hóa các cảnh báo mà tất cả Hedley có thể làm, nhưng hy vọng bạn hiểu ý.