Dalam Visual C ++, dimungkinkan untuk digunakan #pragma warning (disable: ...)
. Saya juga menemukan bahwa di GCC Anda dapat mengganti setiap flag kompiler file . Bagaimana saya bisa melakukan ini untuk "baris berikutnya", atau dengan push / pop semantik di sekitar area kode menggunakan GCC?
c
gcc
compiler-warnings
pragma
Matt Joiner
sumber
sumber
Jawaban:
Tampaknya ini bisa dilakukan . Saya tidak dapat menentukan versi GCC yang ditambahkan, tetapi sekitar sebelum Juni 2010.
Ini sebuah contoh:
sumber
push
dan duapop
s - mungkin yang lainpush
di awal hilang?Untuk menjaring semuanya, ini adalah contoh menonaktifkan sementara peringatan:
Anda dapat memeriksa dokumentasi GCC pada pragma diagnostik untuk detail lebih lanjut.
sumber
gcc-4.9
hanya mengabaikan baris ini sepenuhnya.TL; DR : Jika itu berfungsi, hindari, atau gunakan specifier seperti
__attribute__
, sebaliknya_Pragma
.Ini adalah versi singkat dari artikel blog saya Suppressing Warnings in GCC and Clang .
Pertimbangkan yang berikut ini
Makefile
untuk membangun
puts.c
kode sumber berikutIni tidak akan dikompilasi karena
argc
tidak digunakan, dan pengaturannya hardcore (-W -Wall -pedantic -Werror
).Ada 5 hal yang bisa Anda lakukan:
__attribute__
_Pragma
#pragma
Memperbaiki sumbernya
Upaya pertama harus memeriksa apakah kode sumber dapat ditingkatkan untuk menghilangkan peringatan. Dalam hal ini kami tidak ingin mengubah algoritma hanya karena itu, seperti
argc
yang berlebihan dengan!*argv
(NULL
setelah elemen terakhir).Menggunakan specifier deklarasi, seperti
__attribute__
Jika Anda beruntung, standar menyediakan spek untuk situasi Anda, misalnya
_Noreturn
.__attribute__
adalah ekstensi GCC berpemilik (didukung oleh Dentang dan beberapa kompiler lainarmcc
juga) dan tidak akan dipahami oleh banyak kompiler lain. Masukkan ke__attribute__((unused))
dalam makro jika Anda ingin kode portabel._Pragma
operator_Pragma
dapat digunakan sebagai alternatif#pragma
.Keuntungan utama dari
_Pragma
operator adalah Anda bisa memasukkannya ke dalam makro, yang tidak mungkin dengan#pragma
arahan.Kelemahan: Ini hampir nuklir taktis, karena ia bekerja berdasarkan garis daripada berbasis deklarasi.
The
_Pragma
Operator diperkenalkan di C99.#pragma
pengarahan.Kami dapat mengubah kode sumber untuk menekan peringatan untuk wilayah kode, biasanya seluruh fungsi:
Kelemahan: Ini hampir nuklir taktis, karena ia bekerja berdasarkan garis daripada berbasis deklarasi.
Perhatikan bahwa sintaksis serupa ada di dentang .
Menekan peringatan pada baris perintah untuk satu file
Kita bisa menambahkan baris berikut ke
Makefile
untuk menekan peringatan khusus untuk put:Ini mungkin tidak ingin Anda inginkan dalam kasus khusus Anda, tetapi mungkin membantu bacaan lain yang berada dalam situasi yang sama.
sumber
improving the source
itu juga akan berfungsi untuk mengubah deklarasi main menjadiint main(int, const char* argv[]) { ... }
dengan tidak memberikan argumen nama, Anda mengatakan kepada kompiler itu akan tidak digunakan.gcc
jugaclang
.#define UNUSED(x) ((void)x)
digunakan untuk membungkam peringatan. Saya pikir itu di ReactOS?_Pragma("GCC diagnostic pop") \
seharusnya_Pragma("GCC diagnostic pop")
saya pikir.Ini harus melakukan trik untuk gcc, dentang dan msvc
Dapat dipanggil dengan mis:
lihat https://gcc.gnu.org/onlinedocs/cpp/Pragmas.html , http://clang.llvm.org/docs/UsersManual.html#controlling-diagnostics-via-pragmas dan https://msdn.microsoftoft .com / de-DE / library / d9x1s805.aspx untuk lebih jelasnya
Anda memerlukan setidaknya versi 4.02 untuk menggunakan pragma semacam ini untuk gcc, tidak yakin tentang msvc dan dentang tentang versi.
Sepertinya penanganan push pop pragma untuk gcc sedikit rusak. Jika Anda mengaktifkan peringatan lagi, Anda masih mendapatkan peringatan untuk blok yang ada di dalam blok DISABLE_WARNING / ENABLE_WARNING. Untuk beberapa versi gcc berfungsi, untuk sebagian tidak.
sumber
Ganti "-Wformat" dengan nama bendera peringatan Anda.
AFAIK tidak ada cara untuk menggunakan push / pop semantik untuk opsi ini.
sumber
Saya memiliki masalah yang sama dengan perpustakaan eksternal seperti header ROS. Saya suka menggunakan opsi berikut di CMakeLists.txt untuk kompilasi yang lebih ketat:
Namun melakukan ini menyebabkan semua jenis kesalahan pedantic di perpustakaan yang disertakan secara eksternal juga. Solusinya adalah untuk menonaktifkan semua peringatan dahsyat sebelum Anda menyertakan perpustakaan eksternal dan mengaktifkan kembali seperti ini:
sumber
Saya tahu pertanyaannya adalah tentang GCC, tetapi untuk orang yang mencari cara melakukan ini di kompiler lain dan / atau banyak ...
TL; DR
Anda mungkin ingin melihat Hedley , yang merupakan header domain publik C / C ++ tunggal yang saya tulis yang memberikan banyak hal untuk Anda. Saya akan memasukkan bagian singkat tentang cara menggunakan Hedley untuk semua ini di akhir posting ini.
Menonaktifkan peringatan
#pragma warning (disable: …)
memiliki padanan dalam kebanyakan kompiler:#pragma warning(disable:4996)
#pragma GCC diagnostic ignored "-W…"
mana elipsis adalah nama peringatan; misalnya ,#pragma GCC diagnostic ignored "-Wdeprecated-declarations
.#pragma clang diagnostic ignored "-W…"
. Sintaksisnya pada dasarnya sama dengan GCC, dan banyak dari nama peringatan itu sama (walaupun banyak yang tidak).#pragma warning(disable:1478 1786)
.diag_suppress
pragma:#pragma diag_suppress 1215,1444
diag_suppress
pragma dengan sintaks yang sama (tetapi nomor peringatan berbeda!) Dengan PGI:pragma diag_suppress 1291,1718
error_messages
pragma. Mengganggu, peringatan berbeda untuk kompiler C dan C ++. Kedua menonaktifkan ini pada dasarnya peringatan yang sama:#pragma error_messages(off,E_DEPRECATED_ATT,E_DEPRECATED_ATT_MESS)
#pragma error_messages(off,symdeprecated,symdeprecated2)
diag_suppress
seperti PGI dan TI, tetapi sintaksnya berbeda. Beberapa nomor peringatannya sama, tetapi saya yang lain telah menyimpang:#pragma diag_suppress=Pe1444,Pe1215
#pragma warn(disable:2241)
Untuk sebagian besar kompiler, sebaiknya memeriksa versi kompiler sebelum menonaktifkannya, jika tidak, Anda hanya akan memicu peringatan lain. Misalnya, GCC 7 menambahkan dukungan untuk
-Wimplicit-fallthrough
peringatan, jadi jika Anda peduli dengan GCC sebelum 7, Anda harus melakukan sesuatu sepertiUntuk dentang dan kompiler yang didasarkan pada dentang seperti versi yang lebih baru dari XL C / C ++ dan armclang, Anda dapat memeriksa untuk melihat apakah kompiler tahu tentang peringatan tertentu menggunakan
__has_warning()
makro.Tentu saja Anda juga harus memeriksa untuk melihat apakah
__has_warning()
makro ada:Anda mungkin tergoda untuk melakukan sesuatu seperti
Jadi Anda bisa menggunakan
__has_warning
sedikit lebih mudah. Dentang bahkan menyarankan sesuatu yang mirip dengan__has_builtin()
makro di manual mereka. Jangan lakukan ini . Kode lain mungkin memeriksa__has_warning
dan kembali memeriksa versi kompiler jika tidak ada, dan jika Anda menentukan__has_warning
Anda akan memecahkan kode mereka. Cara yang tepat untuk melakukan ini adalah membuat makro di namespace Anda. Sebagai contoh:Maka Anda dapat melakukan hal-hal seperti
Mendorong dan bermunculan
Banyak kompiler juga mendukung cara untuk mendorong dan mengeluarkan peringatan ke tumpukan. Misalnya, ini akan menonaktifkan peringatan pada GCC untuk satu baris kode, lalu mengembalikannya ke status sebelumnya:
Tentu saja tidak ada banyak kesepakatan di antara kompiler tentang sintaks:
#pragma GCC diagnostic push
/#pragma GCC diagnostic pop
#pragma clang diagnostic push
/#pragma diagnostic pop
#pragma warning(push)
/#pragma warning(pop)
#pragma warning(push)
/#pragma warning(pop)
#pragma push
/#pragma pop
#pragma diag_push
/#pragma diag_pop
#pragma warning(push)
/#pragma warning(pop)
Jika memori berfungsi, untuk beberapa versi GCC yang sangat lama (seperti 3.x, IIRC) pragma push / pop harus berada di luar fungsi.
Menyembunyikan detail berdarah
Untuk sebagian besar kompiler dimungkinkan untuk menyembunyikan logika di balik makro yang menggunakan
_Pragma
, yang diperkenalkan pada C99. Bahkan dalam mode non-C99, kebanyakan kompiler mendukung_Pragma
; pengecualian besar adalah MSVC, yang memiliki__pragma
kata kunci sendiri dengan sintaks yang berbeda. Standar_Pragma
mengambil string, versi Microsoft tidak:Secara kasar setara, setelah diproses, untuk
Ini memungkinkan kami membuat makro sehingga kami dapat menulis kode seperti
Dan sembunyikan semua pemeriksaan versi jelek dalam definisi makro.
Cara mudah: Hedley
Sekarang setelah Anda memahami mekanisme cara melakukan hal-hal seperti ini dengan mudah sambil menjaga kode Anda tetap bersih, Anda memahami apa salah satu proyek saya, Hedley . Alih-alih menggali melalui banyak dokumentasi dan / atau menginstal versi sebanyak mungkin kompiler untuk mengujinya, Anda bisa memasukkan Hedley (ini adalah header domain C / C ++ publik tunggal) dan selesai melakukannya. Sebagai contoh:
Akan menonaktifkan peringatan tentang memanggil fungsi yang sudah tidak digunakan lagi di GCC, dentang, ICC, PGI, MSVC, TI, IAR, ODS, Pelles, dan mungkin yang lain (saya mungkin tidak akan repot memperbarui jawaban ini ketika saya memperbarui Hedley). Dan, pada kompiler yang tidak dikenal berfungsi, makro tidak akan diproses apa-apa, jadi kode Anda akan terus bekerja dengan kompiler apa pun. Tentu saja
HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
bukan satu-satunya peringatan yang diketahui Hedley, juga tidak menonaktifkan peringatan yang bisa dilakukan Hedley, tapi mudah-mudahan Anda mendapatkan idenya.sumber
Alih-alih membungkam peringatan, gaya gcc biasanya menggunakan konstruksi standar C atau
__attribute__
ekstensi untuk memberi tahu kompiler lebih banyak tentang niat Anda. Misalnya, peringatan tentang penugasan yang digunakan sebagai suatu kondisi ditekan dengan menempatkan penugasan dalam tanda kurung, yaituif ((p=malloc(cnt)))
bukannyaif (p=malloc(cnt))
. Peringatan tentang argumen fungsi yang tidak digunakan dapat ditekan oleh beberapa hal aneh yang__attribute__
tidak pernah saya ingat, atau dengan penugasan sendiri, dll. Tetapi secara umum saya lebih suka menonaktifkan opsi peringatan yang menghasilkan peringatan untuk hal-hal yang akan terjadi dalam kode yang benar secara global.sumber
if ((p=malloc(cnt)) != NULL) ...
itulah yang dilakukan kompiler di belakang layar.Bagi mereka yang menemukan halaman ini mencari cara untuk melakukan ini di IAR, coba ini:
Lihat http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0472m/chr1359124244797.html untuk referensi.
sumber