Visual C ++에서는을 사용할 수 있습니다 #pragma warning (disable: ...)
. 또한 GCC 에서는 파일 당 컴파일러 플래그를 재정의 할 수 있음을 발견했습니다 . "다음 라인"또는 GCC를 사용하여 코드 영역 주위에 푸시 / 팝 의미를 사용하여이 작업을 수행하려면 어떻게해야합니까?
Visual C ++에서는을 사용할 수 있습니다 #pragma warning (disable: ...)
. 또한 GCC 에서는 파일 당 컴파일러 플래그를 재정의 할 수 있음을 발견했습니다 . "다음 라인"또는 GCC를 사용하여 코드 영역 주위에 푸시 / 팝 의미를 사용하여이 작업을 수행하려면 어떻게해야합니까?
답변:
이 작업을 수행 할 수있는 것 같습니다 . 추가 된 GCC 버전을 확인할 수 없지만 2010 년 6 월 이전입니다.
예를 들면 다음과 같습니다.
#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
- push
처음에 다른 것이 없을 수 있습니까?
모든 것을 제거하기 위해 다음은 일시적 으로 경고를 비활성화 하는 예입니다 .
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-result"
write(foo, bar, baz);
#pragma GCC diagnostic pop
자세한 내용 은 진단 pragma에 대한 GCC 설명서를 확인할 수 있습니다 .
gcc-4.9
이 줄을 완전히 무시합니다.
TL; DR : 작동하는 경우 피하거나 __attribute__
그렇지 않은 경우와 같은 지정자를 사용하십시오 _Pragma
.
이것은 내 블로그 기사 GCC 및 Clang의 경고 억제 의 짧은 버전입니다 .
다음을 고려하세요 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
입니다. 지시문으로 는 불가능합니다 .
단점 : 선언 기반이 아니라 라인 기반으로 작동하기 때문에 거의 전술적 인 핵무기입니다.
_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
단점 : 선언 기반이 아니라 라인 기반으로 작동하기 때문에 거의 전술적 인 핵무기입니다.
clang에도 비슷한 구문이 있습니다 .
Makefile
put에 특별히 경고를 표시하지 않기 위해 다음 행을 추가 할 수 있습니다 .
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
gcc에 이러한 종류의 pragma를 사용하려면 버전 4.02 이상이 필요합니다. 버전에 대해서는 msvc 및 clang에 대해서는 확실하지 않습니다.
gcc의 푸시 팝 pragma 처리가 약간 손상 된 것처럼 보입니다. 경고를 다시 활성화하면 DISABLE_WARNING / ENABLE_WARNING 블록 내부에있는 블록에 대한 경고가 계속 나타납니다. 일부 버전의 gcc에서는 작동하지만 일부 버전에서는 작동하지 않습니다.
#pragma GCC diagnostic ignored "-Wformat"
"-Wformat"을 경고 플래그 이름으로 바꾸십시오.
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에 관한 것이지만 다른 컴파일러 및 / 또는 여러 컴파일러 에서이 작업을 수행하는 방법을 찾는 사람들에게는 ...
당신은 한 번 봐 걸릴 수도 있습니다 헤 들리 않습니다 내가 쓴 공개 도메인 단일 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가 있습니다 :#pragma diag_suppress 1215,1444
diag_suppress
PGI와 같은 구문 (하지만 다른 경고 번호!)을 가진 pragma 가 있습니다 .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
경고에 대한 지원을 추가 했으므로 7 이전에 GCC에 관심이있는 경우 다음과 같은 작업을 수행해야합니다.
#if defined(__GNUC__) && (__GNUC__ >= 7)
# pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
#endif
최신 XL C / C ++ 및 armclang 버전과 같은 clang 기반 컴파일러 및 clang의 경우 __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
좀 더 쉽게 사용할 수 있습니다. Clang __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)의 경우 푸시 / 팝 프라그 마가 함수 외부 에 있어야합니다.
대부분의 컴파일러의 경우 _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
그리고 매크로 정의에서 모든 추악한 버전 확인을 숨 깁니다.
코드를 깨끗하게 유지하면서 이와 같은 작업을 수행하는 방법의 메커니즘을 이해 했으므로 Hedley 가 내 프로젝트 중 하나를 이해합니다 . 테스트 할 수있는 많은 문서를 파고 들거나 많은 버전의 컴파일러를 설치하는 대신 Hedley (단일 퍼블릭 도메인 C / C ++ 헤더)를 포함시키고 완료 할 수 있습니다. 예를 들면 다음과 같습니다.
#include "hedley.h"
HEDLEY_DIAGNOSTIC_PUSH
HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
call_deprecated();
HEDLEY_DIAGNOSTIC_POP
GCC, clang, ICC, PGI, MSVC, TI, IAR, ODS, Pelles 및 기타에서 더 이상 사용되지 않는 함수 호출에 대한 경고를 비활성화합니다 (Hedley를 업데이트 할 때이 답변을 업데이트하지 않을 것입니다). 그리고 작동하지 않는 컴파일러에서는 매크로가 아무 것도 사전 처리되지 않으므로 코드는 계속 모든 컴파일러에서 작동합니다. 물론 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를 참조하십시오.