programing

코드 몇 줄에 대해 GCC 경고를 비활성화하는 방법

goodcopy 2022. 8. 1. 21:54
반응형

코드 몇 줄에 대해 GCC 경고를 비활성화하는 방법

Visual C++에서는 를 사용할 수 있습니다.또한 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 */

다음 예에서는 모든 것을 망으로 표시하기 위해 경고를 일시적으로 비활성화하는 방법을 보여 줍니다.

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-result"
    write(foo, bar, baz);
#pragma GCC diagnostic pop

상세한 것에 대하여는, 진단 플러그마에 관한 GCC 메뉴얼을 참조해 주세요.

GCC에 관한 질문인 것은 알지만, 다른 컴파일러나 여러 컴파일러에서 이 작업을 수행하는 방법을 찾고 있는 분에게는…

TL;DR

Hedley는 제가 작성한 퍼블릭 도메인 단일 C/C++ 헤더로 많은 기능을 합니다.이 모든 것에 Hedley를 사용하는 방법에 대한 간단한 섹션은 이 투고 끝에 게재하겠습니다.

경고 비활성화

#pragma warning (disable: …)대부분의 컴파일러에는 다음과 같은 기능이 있습니다.

  • MSVC:#pragma warning(disable:4996)
  • GCC:#pragma GCC diagnostic ignored "-W…"여기서 줄임표는 경고의 이름입니다. 예를 들어,#pragma GCC diagnostic ignored "-Wdeprecated-declarations.
  • 쨍그랑:#pragma clang diagnostic ignored "-W…"하지 않습니다 구문은 기본적으로 GCC와 동일하며 경고 이름 중 대부분은 동일합니다(다수는 동일하지 않습니다).
  • 인텔 C++ 컴파일러 (ICC) :MSVC 구문을 사용하되 경고 번호는 완전히 다르다는 점에 유의하십시오.예:#pragma warning(disable:1478 1786).
  • PGI/Nvidia:이 있습니다.diag_suppress 플러 prag:#pragma diag_suppress 1215,1444모든 경고 수가 20.7(최초의 Nvidia HPC 릴리즈)에서1개 증가하였습니다.
  • TI (CCS) : 여기 있습니다.diag_suppress같은 , 번호: PGI는 다음과 같습니다.pragma diag_suppress 1291,1718
  • Oracle Developer Studio (ODS) (Suncc) : 에는error_messages도 C 컴파일러의 C++로 하다두 가지 모두 기본적으로 동일한 경고를 비활성화합니다.
    • C:#pragma error_messages(off,E_DEPRECATED_ATT,E_DEPRECATED_ATT_MESS)
    • C++:#pragma error_messages(off,symdeprecated,symdeprecated2)
  • IAR: 또한 사용diag_suppressPGI TI p p 릅 릅 릅 릅 릅 릅 p p p p 숫자 도 있습니다. 즉, 서로 숫자입니다.#pragma diag_suppress=Pe1444,Pe1215
  • Pelles C: MSVC와 비슷하지만 숫자는 다릅니다.#pragma warn(disable:2241)

대부분의 컴파일러에서는 디세블로 하기 전에 컴파일러 버전을 확인하는 것이 좋습니다.그렇지 않으면 또 다른 경고가 발생합니다.를 들어,에서는 「」, 「GCC 7」의되었습니다.-Wimplicit-fallthrough 7시 이전에 GCC를 신경 쓴다면 GCC를 신경 쓰다, 7시 이전에 GCC를 신경 쓰다, 이렇게 .

#if defined(__GNUC__) && (__GNUC__ >= 7)
#  pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
#endif

Clang 및 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

밀어서 터뜨리다

많은 컴파일러는 경고를 스택에 푸시하여 팝업하는 방법도 지원합니다.예를 들어, 1줄의 코드에 대해 GCC에 대한 경고를 디세블로 한 후 이전 상태로 되돌립니다.

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated"
call_deprecated_function();
#pragma GCC diagnostic pop

물론 다음 구문에 대한 컴파일러 간의 합의는 많지 않습니다.

  • GCC 4.6+:#pragma GCC diagnostic push#pragma GCC diagnostic pop
  • 쾅:#pragma clang diagnostic push#pragma diagnostic pop
  • 13+ (13+) :#pragma warning(push)#pragma warning(pop)
  • MSVC 15+ (Visual Studio 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+ (Pelles C 2.90+) :#pragma warning(push)#pragma warning(pop)

메모리가 기능하는 경우 GCC의 매우 오래된 버전(3.x, IIRC 등)의 경우 푸시/팝 플러그마는 함수 밖에 있어야 합니다.

피투성이의 디테일을 숨기다

에 있는 수 _PragmaC99에서 도입되었습니다.C99 이외의 모드에서도 대부분의 컴파일러는_Pragma; 큰 예외는인 MSVC, MSVC, MSVC가 .__pragma키워드를 지정합니다. ★★_Pragma는 문자열을 MicrosoftMicrosoft 버전에는 없습니다.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 C 및 기타에서 권장되지 않는 함수를 호출하는 경고를 비활성화합니다(Hedley 업데이트 시 이 답변을 업데이트하지 않습니다).에서는, 에, 코드는 합니다.입니다.HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED헤들리가 알고 있는 유일한 경고도 아니고, 헤들리가 할 수 있는 모든 경고도 무효로 하는 것도 아닙니다만, 이해하시길 바랍니다.

TL;DR: 다음과 같은 지정자를 사용하는 경우__attribute__그 이외의 경우_Pragma.

이것은 제 블로그 기사 Suppressing Warnings in GCC and 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 の (( is is is(clclcl및clclclclclclclclclclclclclclclclclcl ) 。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")

의요 of of의 _Pragma 수 .이것은 operator의 operator에서는 할 수 .교환수, 교환수#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담다

CPPFLAGS:=-std=c11 -W -Wall -pedantic -Werror

.PHONY: all
all: puts

puts.o: CPPFLAGS+=-Wno-unused-parameter

이것은 아마도 여러분이 특정한 경우에 원하는 것이 아닐지도 모르지만, 비슷한 상황에 처한 다른 독자들에게 도움이 될 수도 있습니다.

#pragma GCC diagnostic ignored "-Wformat"

"-Wformat"을 경고 플래그 이름으로 대체합니다.

AFAIK는 이 옵션에 push/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, ClangMSVC에 문제가 없습니다.

다음과 같이 호출할 수 있습니다.

DISABLE_WARNING(unused-variable,unused-variable,42)
[.... some code with warnings in here ....]
ENABLE_WARNING(unused-variable,unused-variable,42)

자세한 내용은 7 Pragmas, Controlling Diagnostics via Pragmas and Pragma 명령__pragma 키워드를 참조하십시오.

이러한 종류의 플러그마를 GCC에 사용하려면 버전 4.02 이상이 필요합니다.MSVC와 Clang에 대해서는 잘 모르겠습니다.

GCC의 Push Pop 플러그마 처리가 약간 망가진 것 같습니다.경고를 다시 활성화해도 DISABLE_WARNING/ENABLE_WARNING 블록 내에 있던 블록에 대한 경고가 계속 표시됩니다.GCC 버전에 따라서는 동작하고 있지 않은 경우도 있습니다.

ROS 헤더와 같은 외부 라이브러리에도 같은 문제가 있었습니다.CMake Lists에서 다음 옵션을 사용하고 싶습니다.보다 엄격한 컴파일을 위해 txt:

set(CMAKE_CXX_FLAGS "-std=c++0x -Wall -Wextra -Wstrict-aliasing -pedantic -Werror -Wunreachable-code ${CMAKE_CXX_FLAGS}")

그러나 이렇게 하면 외부에서 포함된 라이브러리에서도 모든 종류의 현학적 오류가 발생합니다.해결책은 외부 라이브러리를 포함하기 전에 모든 현학적 경고를 비활성화하고 다음과 같이 다시 활성화하는 것입니다.

// Save compiler switches
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpedantic"

// Bad headers with a problem goes here
#include <ros/ros.h>
#include <sensor_msgs/LaserScan.h>

// Restore compiler switches
#pragma GCC diagnostic pop

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

참고는 공식 문서를 참조하십시오.

시키는 것이 C 또는 합니다.__attribute__확장자를 사용하여 컴파일러에 사용자의 의도를 자세히 알립니다.

에 관한 는, 괄호 안에 if ((p=malloc(cnt)))if (p=malloc(cnt)).

되지 않는 홀수인 경우 할 수 .__attribute__「 」 「 」 、 「 」 、 「 」

그러나 일반적으로 올바른 코드로 발생하는 경고에 대해 경고를 생성하는 경고 옵션을 전체적으로 비활성화하는 것이 좋습니다.

언급URL : https://stackoverflow.com/questions/3378560/how-to-disable-gcc-warnings-for-a-few-lines-of-code

반응형