ใน Visual C ++ #pragma warning (disable: ...)
มันเป็นไปได้ที่จะใช้งาน นอกจากนี้ผมพบว่าใน GCC คุณสามารถแทนที่ต่อธงคอมไพเลอร์ไฟล์ ฉันจะทำสิ่งนี้สำหรับ "บรรทัดถัดไป" หรือด้วยความหมายของพุช / ป๊อปรอบ ๆ พื้นที่ของรหัสโดยใช้ GCC ได้อย่างไร
ใน Visual C ++ #pragma warning (disable: ...)
มันเป็นไปได้ที่จะใช้งาน นอกจากนี้ผมพบว่าใน GCC คุณสามารถแทนที่ต่อธงคอมไพเลอร์ไฟล์ ฉันจะทำสิ่งนี้สำหรับ "บรรทัดถัดไป" หรือด้วยความหมายของพุช / ป๊อปรอบ ๆ พื้นที่ของรหัสโดยใช้ GCC ได้อย่างไร
คำตอบ:
มันจะปรากฏขึ้นนี้สามารถทำได้ ฉันไม่สามารถระบุรุ่นของ GCC ที่เพิ่มเข้ามาได้ แต่ก่อนหน้านี้บางครั้งก่อนเดือนมิถุนายน 2010
นี่คือตัวอย่าง:
#pragma GCC diagnostic error "-Wuninitialized"
foo(a); /* error is given for this one */
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wuninitialized"
foo(b); /* no diagnostic for this one */
#pragma GCC diagnostic pop
foo(c); /* error is given for this one */
#pragma GCC diagnostic pop
foo(d); /* depends on command line options */
push
และสองpop
s - อาจเป็นอีกpush
จุดเริ่มต้นหายไป?
หากต้องการรวมทุกอย่างออกมานี่เป็นตัวอย่างของการปิดใช้งานคำเตือนชั่วคราว :
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-result"
write(foo, bar, baz);
#pragma GCC diagnostic pop
คุณสามารถตรวจสอบเอกสาร GCC เกี่ยวกับการวินิจฉัยเพื่อดูรายละเอียดเพิ่มเติม
gcc-4.9
ไม่สนใจบรรทัดนี้อย่างสมบูรณ์
TL; DR : หากการทำงานหลีกเลี่ยงหรือใช้ specifiers ชอบมิฉะนั้น__attribute__
_Pragma
นี่เป็นบทความสั้น ๆ ในบล็อกของฉัน การระงับคำเตือนใน GCC และเสียงดังกราว
พิจารณาดังต่อไปนี้ Makefile
CPPFLAGS:=-std=c11 -W -Wall -pedantic -Werror
.PHONY: all
all: puts
สำหรับการสร้างputs.c
ซอร์สโค้ดต่อไปนี้
#include <stdio.h>
int main(int argc, const char *argv[])
{
while (*++argv) puts(*argv);
return 0;
}
มันจะไม่รวบรวมเพราะargc
ไม่ได้ใช้และการตั้งค่าจะไม่ยอมใครง่ายๆ ( -W -Wall -pedantic -Werror
)
มี 5 สิ่งที่คุณสามารถทำได้:
__attribute__
_Pragma
#pragma
ความพยายามครั้งแรกควรตรวจสอบว่าสามารถปรับปรุงซอร์สโค้ดเพื่อกำจัดคำเตือนได้หรือไม่ ในกรณีนี้เราไม่ต้องการเปลี่ยนอัลกอริทึมเพียงเพราะสิ่งนั้นเช่นเดียวargc
กับที่ซ้ำซ้อนกับ!*argv
( NULL
หลังจากองค์ประกอบสุดท้าย)
__attribute__
#include <stdio.h>
int main(__attribute__((unused)) int argc, const char *argv[])
{
while (*++argv) puts(*argv);
return 0;
}
_Noreturn
ถ้าคุณโชคดีมาตรฐานให้ระบุสำหรับสถานการณ์ของคุณเช่น
__attribute__
เป็นส่วนขยาย GCC ที่เป็นกรรมสิทธิ์ (สนับสนุนโดย Clang และคอมไพเลอร์อื่น ๆ เช่นarmcc
กัน) และจะไม่สามารถเข้าใจได้โดยคอมไพเลอร์อื่น ๆ ใส่__attribute__((unused))
ในแมโครถ้าคุณต้องการโค้ดแบบพกพา
_Pragma
ผู้ประกอบการ_Pragma
#pragma
สามารถนำมาใช้เป็นทางเลือกให้กับ
#include <stdio.h>
_Pragma("GCC diagnostic push")
_Pragma("GCC diagnostic ignored \"-Wunused-parameter\"")
int main(int argc, const char *argv[])
{
while (*++argv) puts(*argv);
return 0;
}
_Pragma("GCC diagnostic pop")
ข้อได้เปรียบหลักของ_Pragma
โอเปอเรเตอร์คือคุณสามารถใส่ไว้ในมาโครซึ่งไม่สามารถทำได้ด้วย#pragma
คำสั่ง
ข้อเสีย: มันเกือบจะเป็นยุทธวิธีนูคเพราะมันทำงานแบบ line-based แทนการประกาศตาม
_Pragma
ผู้ประกอบการได้รับการแนะนำใน C99
#pragma
คำสั่งเราสามารถเปลี่ยนซอร์สโค้ดเพื่อไม่ให้มีการเตือนสำหรับส่วนของโค้ดซึ่งโดยทั่วไปจะเป็นฟังก์ชั่นทั้งหมด:
#include <stdio.h>
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
int main(int argc, const char *argv[])
{
while (*++argc) puts(*argv);
return 0;
}
#pragma GCC diagnostic pop
ข้อเสีย: มันเกือบจะเป็นยุทธวิธีนูคเพราะมันทำงานแบบ line-based แทนการประกาศตาม
โปรดทราบว่าไวยากรณ์ที่คล้ายกันอยู่ในเสียงดังกราว
เราสามารถเพิ่มบรรทัดต่อไปนี้ในMakefile
การระงับคำเตือนโดยเฉพาะสำหรับการใส่:
CPPFLAGS:=-std=c11 -W -Wall -pedantic -Werror
.PHONY: all
all: puts
puts.o: CPPFLAGS+=-Wno-unused-parameter
นี่อาจไม่ต้องการให้คุณต้องการในกรณีเฉพาะของคุณ แต่มันอาจช่วยให้ผู้อ่านคนอื่น ๆ ที่อยู่ในสถานการณ์ที่คล้ายกัน
improving the source
มันจะทำงานเพื่อเปลี่ยนการประกาศของ main int main(int, const char* argv[]) { ... }
โดยไม่ให้อาร์กิวเมนต์ชื่อคุณบอกคอมไพเลอร์ว่ามันจะไม่ได้ใช้
gcc
clang
#define UNUSED(x) ((void)x)
ใช้เพื่อปิดเสียงคำเตือน ฉันคิดว่ามันเป็นใน ReactOS?
_Pragma("GCC diagnostic pop") \
ควรจะเป็น_Pragma("GCC diagnostic pop")
อย่างนั้น
#define DIAG_STR(s) #s
#define DIAG_JOINSTR(x,y) DIAG_STR(x ## y)
#ifdef _MSC_VER
#define DIAG_DO_PRAGMA(x) __pragma (#x)
#define DIAG_PRAGMA(compiler,x) DIAG_DO_PRAGMA(warning(x))
#else
#define DIAG_DO_PRAGMA(x) _Pragma (#x)
#define DIAG_PRAGMA(compiler,x) DIAG_DO_PRAGMA(compiler diagnostic x)
#endif
#if defined(__clang__)
# define DISABLE_WARNING(gcc_unused,clang_option,msvc_unused) DIAG_PRAGMA(clang,push) DIAG_PRAGMA(clang,ignored DIAG_JOINSTR(-W,clang_option))
# define ENABLE_WARNING(gcc_unused,clang_option,msvc_unused) DIAG_PRAGMA(clang,pop)
#elif defined(_MSC_VER)
# define DISABLE_WARNING(gcc_unused,clang_unused,msvc_errorcode) DIAG_PRAGMA(msvc,push) DIAG_DO_PRAGMA(warning(disable:##msvc_errorcode))
# define ENABLE_WARNING(gcc_unused,clang_unused,msvc_errorcode) DIAG_PRAGMA(msvc,pop)
#elif defined(__GNUC__)
#if ((__GNUC__ * 100) + __GNUC_MINOR__) >= 406
# define DISABLE_WARNING(gcc_option,clang_unused,msvc_unused) DIAG_PRAGMA(GCC,push) DIAG_PRAGMA(GCC,ignored DIAG_JOINSTR(-W,gcc_option))
# define ENABLE_WARNING(gcc_option,clang_unused,msvc_unused) DIAG_PRAGMA(GCC,pop)
#else
# define DISABLE_WARNING(gcc_option,clang_unused,msvc_unused) DIAG_PRAGMA(GCC,ignored DIAG_JOINSTR(-W,gcc_option))
# define ENABLE_WARNING(gcc_option,clang_option,msvc_unused) DIAG_PRAGMA(GCC,warning DIAG_JOINSTR(-W,gcc_option))
#endif
#endif
สิ่งนี้ควรทำเคล็ดลับสำหรับ gcc, clang และ msvc
สามารถเรียกด้วยเช่น:
DISABLE_WARNING(unused-variable,unused-variable,42)
[.... some code with warnings in here ....]
ENABLE_WARNING(unused-variable,unused-variable,42)
ดูhttps://gcc.gnu.org/onlinedocs/cpp/Pragmas.html , http://clang.llvm.org/docs/UsersManual.html#controlling-diagnostics-via-pragmasและhttps://msdn.microsoft .com / de-DE / library / d9x1s805.aspxสำหรับรายละเอียดเพิ่มเติม
คุณต้องการอย่างน้อยรุ่น 4.02 เพื่อใช้ pragmas ประเภทนี้สำหรับ gcc ไม่แน่ใจเกี่ยวกับ msvc และ clang เกี่ยวกับเวอร์ชัน
ดูเหมือนว่าการกดปุ่มป๊อปอัปการจัดการสำหรับ gcc จะหักนิดหน่อย หากคุณเปิดใช้งานคำเตือนอีกครั้งคุณจะยังคงได้รับคำเตือนสำหรับบล็อกที่อยู่ในบล็อค DISABLE_WARNING / ENABLE_WARNING สำหรับ gcc บางรุ่นใช้งานได้สำหรับบางรุ่นใช้ไม่ได้
#pragma GCC diagnostic ignored "-Wformat"
แทนที่ "-Watat" ด้วยชื่อของธงเตือนของคุณ
AFAIK ไม่มีวิธีใช้การกด / ป๊อปอรรถศาสตร์สำหรับตัวเลือกนี้
ฉันมีปัญหาเดียวกันกับห้องสมุดภายนอกเช่นส่วนหัวของ ROS ฉันต้องการใช้ตัวเลือกต่อไปนี้ใน CMakeLists.txt สำหรับการรวบรวมที่เข้มงวดยิ่งขึ้น:
set(CMAKE_CXX_FLAGS "-std=c++0x -Wall -Wextra -Wstrict-aliasing -pedantic -Werror -Wunreachable-code ${CMAKE_CXX_FLAGS}")
อย่างไรก็ตามการทำเช่นนี้ทำให้เกิดข้อผิดพลาดทางอารมณ์ทุกประเภทในห้องสมุดที่รวมอยู่ภายนอกเช่นกัน วิธีแก้ไขคือปิดการใช้งานคำเตือนแบบ pedantic ทั้งหมดก่อนที่จะรวมไลบรารี่ภายนอกและเปิดใช้งานเช่นนี้:
//save compiler switches
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpedantic"
//Bad headers with problem goes here
#include <ros/ros.h>
#include <sensor_msgs/LaserScan.h>
//restore compiler switches
#pragma GCC diagnostic pop
ฉันรู้ว่าคำถามนั้นเกี่ยวกับ GCC แต่สำหรับคนที่กำลังมองหาวิธีการทำสิ่งนี้ในคอมไพเลอร์อื่น ๆ และ / หรือหลายคอมไพเลอร์ ...
คุณอาจต้องการที่จะดูHedleyซึ่งเป็นส่วนหัว C / C ++ เดียวโดเมนสาธารณะที่ฉันเขียนซึ่งไม่มากของสิ่งนี้สำหรับคุณ ฉันจะพูดอย่างย่อเกี่ยวกับวิธีใช้ Hedley สำหรับทั้งหมดนี้ในตอนท้ายของโพสต์นี้
#pragma warning (disable: …)
มีความเท่าเทียมกันในคอมไพเลอร์ส่วนใหญ่:
#pragma warning(disable:4996)
#pragma GCC diagnostic ignored "-W…"
จุดไข่ปลาเป็นชื่อของคำเตือน; เช่น#pragma GCC diagnostic ignored "-Wdeprecated-declarations
,#pragma clang diagnostic ignored "-W…"
เสียงดังกราว: ไวยากรณ์นั้นโดยทั่วไปเหมือนกับของ GCC และชื่อคำเตือนจำนวนมากเหมือนกัน (แม้ว่าจะไม่มาก)#pragma warning(disable:1478 1786)
.diag_suppress
:#pragma diag_suppress 1215,1444
diag_suppress
pragma ที่มีไวยากรณ์เดียวกัน (แต่มีคำเตือนต่างกัน!) กับ PGI:pragma diag_suppress 1291,1718
error_messages
หมาย น่ารำคาญคำเตือนต่างกันสำหรับคอมไพเลอร์ C และ C ++ ทั้งสองอย่างนี้ปิดการใช้งานโดยทั่วไปคำเตือนเดียวกัน
#pragma error_messages(off,E_DEPRECATED_ATT,E_DEPRECATED_ATT_MESS)
#pragma error_messages(off,symdeprecated,symdeprecated2)
diag_suppress
เหมือน PGI และ TI แต่ไวยากรณ์แตกต่างกัน ตัวเลขคำเตือนบางอย่างเหมือนกัน แต่คนอื่น ๆ ก็แยกกัน:#pragma diag_suppress=Pe1444,Pe1215
#pragma warn(disable:2241)
สำหรับคอมไพเลอร์ส่วนใหญ่มักจะเป็นความคิดที่ดีที่จะตรวจสอบเวอร์ชั่นคอมไพเลอร์ก่อนที่จะลองปิดการใช้งานมิฉะนั้นคุณจะจบลงด้วยการเรียกคำเตือนอื่น ตัวอย่างเช่น GCC 7 เพิ่มการสนับสนุนสำหรับ-Wimplicit-fallthrough
คำเตือนดังนั้นหากคุณสนใจ GCC ก่อน 7 คุณควรทำอะไรเช่นนี้
#if defined(__GNUC__) && (__GNUC__ >= 7)
# pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
#endif
สำหรับ clang และ compilers ที่ใช้ clang เช่น XL C / C ++ และ armclang เวอร์ชันใหม่กว่าคุณสามารถตรวจสอบว่าคอมไพเลอร์รู้เกี่ยวกับคำเตือนเฉพาะที่ใช้__has_warning()
แมโครหรือไม่
#if __has_warning("-Wimplicit-fallthrough")
# pragma clang diagnostic ignored "-Wimplicit-fallthrough"
#endif
แน่นอนคุณต้องตรวจสอบเพื่อดูว่ามี__has_warning()
แมโครอยู่หรือไม่:
#if defined(__has_warning)
# if __has_warning("-Wimplicit-fallthrough")
# pragma clang diagnostic ignored "-Wimplicit-fallthrough"
# endif
#endif
คุณอาจถูกล่อลวงให้ทำสิ่งที่ชอบ
#if !defined(__has_warning)
# define __has_warning(warning)
#endif
เพื่อให้คุณสามารถใช้งาน__has_warning
ได้ง่ายขึ้น เสียงดังยังแนะนำสิ่งที่คล้ายกันสำหรับ__has_builtin()
มาโครในคู่มือ อย่าทำอย่างนี้ รหัสอื่นอาจตรวจสอบ__has_warning
และย้อนกลับไปที่การตรวจสอบเวอร์ชันคอมไพเลอร์หากไม่มีอยู่และถ้าคุณกำหนดว่า__has_warning
คุณจะทำผิดรหัส วิธีที่ถูกต้องในการทำเช่นนี้คือการสร้างมาโครในเนมสเปซของคุณ ตัวอย่างเช่น:
#if defined(__has_warning)
# define MY_HAS_WARNING(warning) __has_warning(warning)
#else
# define MY_HAS_WARNING(warning) (0)
#endif
จากนั้นคุณสามารถทำสิ่งต่าง ๆ เช่น
#if MY_HAS_WARNING(warning)
# pragma clang diagnostic ignored "-Wimplicit-fallthrough"
#elif defined(__GNUC__) && (__GNUC__ >= 7)
# pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
#endif
คอมไพเลอร์จำนวนมากยังสนับสนุนวิธีในการพุชและป๊อปคำเตือนลงบนสแต็ก ตัวอย่างเช่นสิ่งนี้จะปิดการใช้งานคำเตือนใน GCC สำหรับรหัสหนึ่งบรรทัดจากนั้นกลับสู่สถานะก่อนหน้า:
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated"
call_deprecated_function();
#pragma GCC diagnostic pop
แน่นอนมีข้อตกลงไม่มากนักในคอมไพเลอร์เกี่ยวกับไวยากรณ์:
#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)
หากหน่วยความจำทำหน้าที่สำหรับ GCC รุ่นเก่า (เช่น 3.x, IIRC) บางรุ่น push / pop pragmas ต้องอยู่นอกฟังก์ชั่น
สำหรับคอมไพเลอร์ส่วนใหญ่สามารถซ่อนตรรกะเบื้องหลังมาโครที่ใช้_Pragma
ซึ่งเปิดตัวใน C99 แม้จะอยู่ในโหมดที่ไม่ใช่ C99 คอมไพเลอร์ส่วนใหญ่สนับสนุน_Pragma
; ข้อยกเว้นใหญ่คือ MSVC ซึ่งมี__pragma
คำหลักของตัวเองที่มีไวยากรณ์ที่แตกต่างกัน มาตรฐาน_Pragma
ใช้สายอักขระเวอร์ชันของ Microsoft ไม่ได้:
#if defined(_MSC_VER)
# define PRAGMA_FOO __pragma(foo)
#else
# define PRAGMA_FOO _Pragma("foo")
#endif
PRAGMA_FOO
เทียบเท่าโดยประมาณเมื่อประมวลผลล่วงหน้าแล้วเป็น
#pragma foo
สิ่งนี้ช่วยให้เราสร้างมาโครเพื่อให้เราสามารถเขียนโค้ดได้
MY_DIAGNOSTIC_PUSH
MY_DIAGNOSTIC_DISABLE_DEPRECATED
call_deprecated_function();
MY_DIAGNOSTIC_POP
และซ่อนการตรวจสอบเวอร์ชั่นที่น่าเกลียดทั้งหมดในนิยามแมโคร
ตอนนี้คุณเข้าใจกลไกของวิธีการที่จะทำสิ่งเช่นนี้ portably ขณะที่การรักษารหัสของคุณสะอาดคุณเข้าใจสิ่งหนึ่งในโครงการของฉันHedleyไม่ แทนที่จะขุดผ่านเอกสารจำนวนมากและ / หรือติดตั้งคอมไพเลอร์ให้มากเท่าที่คุณสามารถทำการทดสอบได้คุณสามารถใส่ Hedley (เป็นโดเมนสาธารณะส่วนหัว C / C ++ เดียว) และทำได้ด้วย ตัวอย่างเช่น:
#include "hedley.h"
HEDLEY_DIAGNOSTIC_PUSH
HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
call_deprecated();
HEDLEY_DIAGNOSTIC_POP
จะปิดการใช้งานคำเตือนเกี่ยวกับการเรียกใช้ฟังก์ชันที่เลิกใช้แล้วใน GCC, เสียงดังกราว, ICC, PGI, MSVC, TI, IAR, ODS, Pelles และอื่น ๆ และในคอมไพเลอร์ที่ไม่ทราบว่าใช้งานได้มาโครนั้นจะถูกประมวลผลล่วงหน้าเป็นอะไรเลยดังนั้นโค้ดของคุณจะทำงานร่วมกับคอมไพเลอร์ต่อไป แน่นอนว่าHEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
ไม่ใช่คำเตือนเพียงอย่างเดียวที่ Hedley รู้และไม่ได้ปิดใช้งานคำเตือนทั้งหมดที่ Hedley สามารถทำได้ แต่หวังว่าคุณจะได้รับแนวคิดนี้
แทนที่จะเงียบคำเตือนสไตล์ gcc มักจะใช้โครงสร้าง C มาตรฐานหรือ__attribute__
ส่วนขยายเพื่อบอกคอมไพเลอร์เพิ่มเติมเกี่ยวกับความตั้งใจของคุณ ยกตัวอย่างเช่นคำเตือนเกี่ยวกับการกำหนดใช้เป็นสภาพที่ถูกระงับโดยการวางที่ได้รับมอบหมายในวงเล็บเช่นแทนif ((p=malloc(cnt)))
if (p=malloc(cnt))
คำเตือนเกี่ยวกับการโต้แย้งฟังก์ชั่นที่ไม่ได้ใช้สามารถระงับได้โดยคี่บางอย่างที่__attribute__
ฉันจำไม่ได้หรือโดยการมอบหมายด้วยตนเอง ฯลฯ แต่โดยทั่วไปฉันชอบเพียงแค่ปิดการใช้งานตัวเลือกคำเตือนทั่วโลกที่สร้างคำเตือนสำหรับสิ่งที่จะเกิดขึ้นในรหัสที่ถูกต้อง
if ((p=malloc(cnt)) != NULL) ...
ว่าเป็นสิ่งที่คอมไพเลอร์กำลังทำอยู่เบื้องหลัง
สำหรับผู้ที่พบหน้านี้กำลังมองหาวิธีการทำสิ่งนี้ใน IAR ลองสิ่งนี้:
#pragma diag_suppress=Pe177
void foo1( void )
{
/* The following line of code would normally provoke diagnostic
message #177-D: variable "x" was declared but never referenced.
Instead, we have suppressed this warning throughout the entire
scope of foo1().
*/
int x;
}
#pragma diag_default=Pe177
ดูhttp://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0472m/chr1359124244797.htmlสำหรับการอ้างอิง