Portability of #Warning Preprocessor Directive

Portability of #warning preprocessor directive

It is likely that if a compiler doesn't support #warning, then it will issue an error. Unlike #pragma, there is no recommendation that the preprocessor ignore directives it doesn't understand.

Having said that, I've used compilers on various different (reasonably common) platforms and they have all supported #warning.

Is there a portable way to print a message from the C preprocessor?

The warning directive is probably the closest you'll get, but it's not entirely platform-independent:

#warning "C Preprocessor got here!"

AFAIK this works on most compilers except MSVC, on which you'll have to use a pragma directive:

#pragma message ( "C Preprocessor got here!" )

How portable is code with #pragma optimize?

#pragma is the sanctioned and portable way for compilers to add non-sanctioned and non-portable language extensions *.

Basically, you never know for sure, and at least one major C++ compiler (g++) does not support this pragma as is.


*:

From the C++ standard (N3242):

16.6 Pragma directive [cpp.pragma]


A preprocessing directive of the form

# pragma pp-tokensopt new-line

causes the implementation to behave in an implementation-defined manner. The behavior might cause translation to fail or cause the translator or the resulting program to behave in a non-conforming manner. Any pragma that is not recognized by the implementation is ignored.

From the C standard (Committee Draft — April 12, 2011):

6.10.6 Pragma directive


Semantics


A preprocessing directive of the form

# pragma pp-tokensopt new-line

where the preprocessing token STDC does not immediately follow pragma in the
directive (prior to any macro replacement)174) causes the implementation to behave in an
implementation-defined manner. The behavior might cause translation to fail or cause the
translator or the resulting program to behave in a non-conforming manner. Any such
pragma that is not recognized by the implementation is ignored.

And here's an example:

int main () {
#pragma omp parallel for
for (int i=0; i<16; ++i) {}
}

A big part of the C and C++ OpenMP API is implemented as #pragmas.

user warnings on msvc AND gcc?

The best solution I've found for this problem is to have the following in a common header:

// compiler_warning.h
#define STRINGISE_IMPL(x) #x
#define STRINGISE(x) STRINGISE_IMPL(x)

// Use: #pragma message WARN("My message")
#if _MSC_VER
# define FILE_LINE_LINK __FILE__ "(" STRINGISE(__LINE__) ") : "
# define WARN(exp) (FILE_LINE_LINK "WARNING: " exp)
#else//__GNUC__ - may need other defines for different compilers
# define WARN(exp) ("WARNING: " exp)
#endif

Then use

#pragma message WARN("your warning message here")

throughout the code instead of #warning

Under MSVC you'll get a message like this:

c:\programming\some_file.cpp(3) : WARNING: your warning message here

Under gcc you'll get:

c:\programming\some_file.cpp:25: note: #pragma message: WARNING: your warning message here

Not perfect, but a reasonable compromise.

Preprocessor directive in middle of c++ function?

When does the #ifdef execute in the above function?

It is executed before "the compiler" sees the code. If the preprocessor knows what the TOOLS_ENABLED symbol is, then the preprocessor continues to pass this code to the compiler.

If the preprocessor does not know what TOOLS_ENABLED is, then it will skip this chunk of code, and not pass that code to the compiler.

Its a common trick, usually to allow "debug" builds to do a bunch of additional validation to affirm that no bug has occured, but to eliminate all this slow doublechecking from "release" builds so that they run super fast.

_Pragma preprocessor operator in Visual C++

Yes, but it's two underscores: __pragma

I'm not sure about how the omp pragma works, however, here's an example using VC++'s optimize pragma:

#define PRAGMA_OPTIMIZE_OFF __pragma(optimize("", off))

// These two lines are equivalent
#pragma optimize("", off)
PRAGMA_OPTIMIZE_OFF

EDIT: I've just confirmed that the omp pragmas can also be used like this:

#define OMP_PARALLEL_FOR __pragma(omp parallel for)

So, yes, your macro should work if defined as follows (note that your original code incorrectly used the stringizing operator #x:

#ifdef _OPENMP
#define PRAGMA_IF_OPENMP(x) __pragma (x)
#else // #ifdef _OPENMP
#define PRAGMA_IF_OPENMP(x)
#endif // #ifdef _OPENMP

GCC 7, -Wimplicit-fallthrough warnings, and portable way to clear them?

GCC expects the marker comment on its own line, like this:

  m_state = BODY;
// fall through
case BODY:

The marker also has to come right before the case label; there cannot be an intervening closing brace }.

fall through is among the markers recognized by GCC. It's not just FALLTHRU. For a full list, see the documentation of the -Wimplicit-fallthrough option. Also see this posting on the Red Hat Developer blog.

C++17 adds a [[fallthrough]] attribute that can be used to suppress such warnings. Note the trailing semicolon:

  m_state = BODY;
[[fallthrough]];
case BODY:

Clang supports -Wimplicit-fallthrough warnings, but does not enable them as part of -Wall or -Wextra. Clang does not recognize comment markers, so the attribute-based suppression has to be used for it (which currently means the non-standard __attribute__((fallthrough)) construct for the C front end).

Note that suppressing the warning with marker comments only works if the compiler actually sees the comment. If the preprocessor runs separately, it needs to be instructed to preserve comments, as with the -C option of GCC. For example, to avoid spurious warnings with ccache, you need to specify the -C flag when compiling, or, with recent versions of ccache, use the keep_comments_cpp option.



Related Topics



Leave a reply



Submit