Preprocessor pragma precedence with #if - c++

I'm using the IAR Embedded Workbench compiler and have an issue with precedence of #pragma with #if.
I'm using #if 0 during development to comment out code.
The #pragma in the code below is to suppress MISRA issues about using hex escape sequences in a C-String.
The code fragment:
#if 0
// Display the glyphs in the font.
// This is debug code.
#pragma diag_suppress=Pm118,Pm003
static const char * text[] =
{
// Limit rows to 20 characters.
" ()+-0123456789Vanot",
"y^?",
"\xE3\x81\x84" "\xE3\x81\x8A" "\xE3\x81\x8C",
};
#pragma diag_default=Pm118,Pm003
static const size_t quantity_text_lines =
sizeof (text) / sizeof(text[0]);
uint16_t y = 150U;
for (unsigned int i = 0u; i < quantity_text_lines; ++i)
{
cmd_text_convert(35U, y,
FONT_HEADING_HANDLE,
0u,
text[i]);
y += 60u;
}
#else
In the above code fragment, I'm getting errors:
Error[Pm118]: hexadecimal escape sequences shall not be used (MISRA C 2004 rule 4.1)
My understanding is that I should not be getting any warnings because the code is inside a #if 0 block.
FYI, when I change #if 0 to #if 1, there are no errors and no warnings generated.
Is the IAR compiler behaving correctly?
What's the ruling regarding the language standard(s) about this?
(The environment is actually C language, but can be compiled in C++ too.)

The standard says that the #pragmas should be ignored, which is consistent with what you see. (The error message was not suppressed.)
6.10.1p6: … Each directive’s condition is checked in order. If it evaluates to false (zero), the group that it controls is skipped: directives are processed only through the name that determines the directive in order to keep track of the level of nested conditionals; the rest of the directives’ preprocessing tokens are ignored, as are the other preprocessing tokens in the group.
(So the only part of #pragma inside #if 0 that is examined is the token pragma, and it is only examined to see if it affects conditional nesting.)
The question is whether the compiler can raise a tokenisation error for a preprocessing token. I'd say that it shouldn't, but there is nothing in the standard which prevents a compiler from generating diagnostics whenever it feels like it. That's a Quality of Implementation (QOI) issue, which is subject to the whim of the consumer, not the standards committee.
In any event, MISRA is not part of the standard.

Is the IAR compiler behaving correctly?
Pragmas or no pragmas, IAR is behaving surprisingly by performing MISRA conformance analysis on the contents of an #if 0 block at all, if indeed that's what it is doing. That seems inconsistent with C preprocessor semantics. Program text -- or more properly, preprocessing tokens -- following a conditional directive whose condition evaluates to zero is processed only enough to recognize the matching #else or #endif, and otherwise is ignored.
Possibly IAR's MISRA scanner is designed to ignore preprocessor conditionals, or to test both alternatives of each one. If it is indeed doing that then it is behaving surprisingly by not recognizing pragmas within those conditional blocks that it would recognize outside them.
I suspect that #rici has it right in supposing that the issue is flagged by IAR's source tokenizer, and then not suppressed on account the relevant #pragmas being ignored (as directed by the language specification). But this is within IAR's control. I would find it hard to accept an argument that IAR is free to implement MISRA compliance scanning, but not free to extend preprocessor behavior to properly support the associated pragma-based controls. Or for that matter, that it can't have preprocessor conditionals control MISRA conformance analysis directly where appropriate.
However,
What's the ruling regarding the language standard(s) about this?
The C language specification does not define any specific significance for the pragmas in question, and it does not define any procedure or semantics for MISRA compliance checking. It specifies that diagnostics must be issued for constraint violations, but does not limit the diagnostics that implementations may issue. This is why above I describe IAR's behavior as surprising rather than wrong. I might go so far as to call it buggy, but not on account of failure to conform to the language specification.

Related

How to disable inline assembly in GCC?

I'm developing an online judge system for programming contests. Since C/C++ inline assembly is not allowed in certain programming contests, I would like to add the same restriction to my system.
I would like to let GCC produce an error when compiling a C/C++ program containing inline assembly, so that any program containing inline assembly will be rejected. Is there a way to achieve that?
Note: disabling inline assembly is just for obeying the rules, not for security concerns.
Is there a way to disable inline assembler in GCC?
Yes there are a couple of methods; none useful for security, only guard-rails that could be worked around intentionally, but will stop people from accidentally using asm in places they didn't realize they shouldn't.
Turn off the asm keyword in the compiler (C only)
To do it in compilation phase, use the parameter -fno-asm. However, keep in mind that this will only affect asm for C, not C++. And not __asm__ or __asm for either language.
Documentation:
-fno-asm
Do not recognize "asm", "inline" or "typeof" as a keyword, so that code can use these words as identifiers. You can use the keywords "__asm__", "__inline__" and "__typeof__" instead. -ansi implies -fno-asm.
In C++ , this switch only affects the "typeof" keyword, since "asm" and "inline" are standard keywords. You may want to use the -fno-gnu-keywords flag instead, which has the same effect. In C99 mode (-std=c99 or -std=gnu99), this switch only affects the "asm" and "typeof" keywords, since "inline" is a standard keyword in ISO C99.
Define the keyword as a macro
You can use the parameters -Dasm=error -D__asm__=error -D__asm=error
Note that this construction is generic. What it does is to create macros. It works pretty much like a #define. The documentation says:
-D name=definition
The contents of definition are tokenized and processed as if they appeared during translation phase three in a #define directive. In particular, the definition will be truncated by embedded newline characters.
...
So what it does is simply to change occurrences of asm, __asm, or __asm__ to error. This is done in the preprocessor phase. You don't have to use error. Just pick anything that will not compile.
Use a macro that fires during compilation
A way to solve it in compilation phase by using a macro, as suggested in comments by zwol, you can use -D'asm(...)=_Static_assert(0,"inline assembly not allowed")'. This will also solve the problem if there exist an identifier called error.
Note: This method requires -std=c11 or higher.
Using grep before using gcc
Yet another way that may be the solution to your problem is to just do a grep in the root of the source tree before compiling:
grep -nr "asm"
This will also catch __asm__ but it may give false positives, for instance is you have a string literal, identifier or comment containing the substring "asm". But in your case you could solve this problem by also forbidding any occurrence of that string anywhere in the source code. Just change the rules.
Possible unexpected problems
Note that disabling assembly can cause other problems. For instance, I could not use stdio.h with this option. It is common that system headers contains inline assembly code.
A way to cheat above methods
Aside from the trivial #undef __asm__, it is possible to execute strings as machine code. See this answer for an example: https://stackoverflow.com/a/18477070/6699433
A piece of the code from the link above:
/* our machine code */
char code[] = {0x55,0x48,0x89,0xe5,0x89,0x7d,0xfc,0x48,
0x89,0x75,0xf0,0xb8,0x2a,0x00,0x00,0x00,0xc9,0xc3,0x00};
/* copy code to executable buffer */
void *buf = mmap (0,sizeof(code),PROT_READ|PROT_WRITE|PROT_EXEC,
MAP_PRIVATE|MAP_ANON,-1,0);
memcpy (buf, code, sizeof(code));
/* run code */
int i = ((int (*) (void))buf)();
The code above is only intended to give a quick idea of how to trick the rules OP has stated. It is not intended to be a good example of how to actually perform it in reality. Furthermore, the code is not mine. It is just a short code quote from the link I supplied. If you have ideas about how to improve it, then please comment on 4pie0:s original post instead.

(v) is actually (*&v) since when?

Could C++ standards gurus please enlighten me:
Since which C++ standard version has this statement failed because (v) seems to be equivalent to (*&v)?
I.e. for example the code:
#define DEC(V) ( ((V)>0)? ((V)-=1) : 0 )
...{...
register int v=1;
int r = DEC(v) ;
...}...
This now produces warnings under -std=c++17 like:
cannot take address of register variable
left hand side of operand must be lvalue
Many C macros enclose ALL macro parameters in parentheses, of which the above is meant only to be a representative example.
The actual macros that produce warnings are for instance
the RTA_* macros in /usr/include/linux/rtnetlink.h.
Short of not using/redefining these macros in C++, is there any workaround?
If you look at the revision summary of the latest C++1z draft, you'd see this in [diff.cpp14.dcl.dcl]
[dcl.stc]
Change: Removal of register storage-class-specifier.
Rationale: Enable repurposing of deprecated keyword in future
revisions of this International Standard.
Effect on original feature: A valid C++ 2014 declaration utilizing the register
storage-class-specifier is ill-formed in this International Standard.
The specifier can simply be removed to retain the original meaning.
The warning may be due to that.
register is no longer a storage class specifier, you should remove it. Compilers may not be issuing the right error or warnings but your code should not have register to begin with
The following is a quote from the standard informing people about what they should do with regards to register in their code (relevant part emphasized), you probably have an old version of that file
C.1.6 Clause 10: declarations [diff.dcl]
Change: In C++, register is not a storage class specifier.
Rationale: The storage class specifier had no effect in C++.
Effect on original feature: Deletion of semantically well-defined feature.
Difficulty of converting: Syntactic transformation.
How widely used: Common.
Your worry is unwarranted since the file in question does not actually contain the register keyword:
grep "register" /usr/include/linux/rtnetlink.h
outputs nothing. Either way, you shouldn't be receiving the warning since:
System headers don't emit warnings by default, at least in GCC
It isn't wise to try to compile a file that belongs to a systems project like the linux kernel in C++ mode, as there may be subtle and nasty breaking changes
Just include the file normally or link the C code to your C++ binary. Report a bug if you really are getting a warning that should normally be suppressed to your compiler vendor.

Extra tokens at end of #ifdef directive

Why does the following code compiles?
#ifdef C++11
// ...
#endif
int main() {}
gcc 4.8.0 gives me the following warning:
extra tokens at end of #ifdef directive
According to the standard, the macro name can contain only letters, digits and underscore character.
Maybe because this?
ISO/IEC 14882:2011
16.1 Conditional inclusion [cpp.cond]
6 Each directive’s condition is checked in order. If it evaluates to
false (zero), the group that it controls is skipped: directives are
processed only through the name that determines the directive in order
to keep track of the level of nested conditionals; the rest of the
directives’ preprocessing tokens are ignored, as are the other
preprocessing tokens in the group. Only the first group whose control
condition evaluates to true (nonzero) is processed. If none of the
conditions evaluates to true, and there is a #else directive, the
group controlled by the #else is processed; lacking a #else directive,
all the groups until the #endif are skipped.151
I can't understand this quote correctly.
As far as C++ is concerted, #ifdef C++11 is a syntax error. There is no rule saying a compiler has to reject a program with a syntax error.
1.4 Implementation compliance [intro.compliance]
The set of diagnosable rules consists of all syntactic and semantic rules in this International Standard except for those rules containing an explicit notation that "no diagnostic is required" or which are described as resulting in "undefined behavior."
[...]
If a program contains a violation of any diagnosable rule or an occurrence of a construct described in this Standard as "conditionally-supported" when the implementation does not support that construct, a conforming implementation shall issue at least one diagnostic message.
A warning is a diagnostic message. The compilers are perfectly within their rights to continue to successfully compile the program, as long as they ensure they show you that one diagnostic message. Since compilers have historically accepted such directives, and accepting such directives does not conflict with the requirements of the standard, they continue to do so.
At least as far as GCC is concerned, you can ask to make all standard-required diagnostics a hard error with the -pedantic-errors option.
$ printf "#ifdef C++11\n#endif\n" | gcc -std=c++11 -pedantic-errors -E -x c++ -
# 1 "<stdin>"
# 1 "<command-line>"
# 1 "<stdin>"
<stdin>:1:9: error: extra tokens at end of #ifdef directive
A #ifdef is defined as follow (taken from §16.1)
# ifdef identifier new-line
With regexp-like notation, an identifier is: [a-zA-Z_][a-zA-Z_0-9]* (*)
The point is: the macro you declare is NOT C++11. It is in fact C (see this live example). The ++11 part is ignored by the preprocessor. The only allowed character after the identifier (which is C) is a new-line, but as said in hvd's answer, from §1.4, a syntax error only force a diagnostic message, here the warning; the only reason I see for this instead of an error is to be compatible with old code, where such names sould have been used.
Also: the quote explains how #ifdef / #elif / #else / #endif work together, not the way conditions are specified.
I do not have a copy of the standard. I used draft n3485 for this answer.
(*) It is possible to have implementation-defined characters in an identifier, but that does not impact your question. Note that variables, class name, macros, ... all follows the same identifier rules.

Why are trigraphs generating errors in modern C++ compilers?

Even in the GCC Compilers, the trigraphs are not getting compiled without explicitly specifying the trigraph attribute.
#include<stdio.h>
int main()
{
int a=4;
if((a==4) ??! (a==5))
printf("\nHello world!");
return 0;
}
This program saved as try.c gets compiled in GCC Compiler only when we specify gcc -Wall -trigraphs try.c and it still shows warnings.
Can you enlist some compilers that will treat and handle trigraphs without any errors or warnings?
Trigraphs were introduced by the 1989 ANSI C standard, and are retained in all later C standards (so far; the upcoming C23 standard will drop them). They also appear in the first ISO C++ standard, published in 1998, and in all later C++ standards up to and including C++14. (Trigraphs were removed in C++17. Thanks to Jonathan Leffler and dyp for tracking down the details.)
Quoting a draft of the C++17 standard:
Effect on original feature: Valid C ++ 2014 code that uses trigraphs
may not be valid or may have different semantics in this International
Standard. Implementations may choose to translate trigraphs as
specified in C ++ 2014 if they appear outside of a raw string literal,
as part of the implementation-defined mapping from physical source
file characters to the basic source character set.
They are not an optional feature in either language (prior to C++17); all conforming compilers must support them and interpret them as specified by the respective language standard.
For example, if this program:
#include <stdio.h>
int main(void) {
if ('|' == '??!') {
puts("ok");
}
else {
puts("oops");
}
return 0;
}
prints oops, then your compiler is non-conforming.
But many, perhaps most, C compilers are not fully conforming by default. As long as a compiler can be made to conform to the standard in some way, that's good enough as far as the standard is concerned. (gcc requires -pedantic and -std=... to do this.)
But even if a compiler is fully conforming, there's nothing in the standard that forbids a compiler from warning about anything it likes. A conforming C compiler must diagnose any violation of a syntax rule or constraint, but it can issue as many additional warnings as it likes -- and it needn't distinguish between required diagnostics and other warnings.
Trigraphs are very rarely used. The vast majority of development systems support directly all the characters for which trigraphs substitute: #, [, \, ], ^, {, |, }, ~.
In fact, it's likely that trigraphs are used accidentally more often than they're used correctly:
fprintf(stderr, "What just happened here??!\n");
Warning about trigraphs that might alter the meaning of a program (relative to the meaning it would have if the language didn't have trigraphs) is both permitted by the ISO standard and IMHO perfectly reasonable. Most compilers probably have options to turn off such warnings.
Conversely, for a C++17 compiler that doesn't implement trigraphs, it would be reasonable to warn about sequences that would have been treated as trigraphs in C++14 or earlier, and/or to provide an option to support trigraphs. Again, an option to disable such warnings would be a good thing.
GCC is allergic to trigraphs. You have to explicitly enable them:
gcc -trigraphs ...
The GCC 4.7.1 manual says:
-trigraphs
Support ISO C trigraphs. The -ansi option (and -std options for strict ISO
C conformance) implies -trigraphs.
It also says:
-Wtrigraphs
Warn if any trigraphs are encountered that might change the meaning of the
program (trigraphs within comments are not warned about). This warning is
enabled by -Wall.
They might be turned off by default.
"Some compilers support an option to turn recognition of trigraphs off, or disable trigraphs by default and require an option to turn them on"
GCC might be one of the latter. Although it should by default ignore with warning, but in this case the ignoring might be causing the compile error
Trigraphs are converted at a very early stage of compilation, and can even be replaced in string literals. This makes errors that arise from trigraph translations very hard to detect (worst off if you consider debugging using a log and you find the output in your source).
The warning you see will help you quickly spot a possible culprit to track the source of the bug. Basically it's warning you that something might not be as you think it is.

Universally compiler independent way of implementing an UNUSED macro in C/C++

When implementing stubs etc. you want to avoid "unused variable" warnings. I've come across a few alternatives of UNUSED() macros over the years, but never one which either is proven to work for "all" compilers, or one which by standard is air tight.
Or are we stuck with #ifdef blocks for each build platform?
EDIT: Due to a number of answers with non c-compliant alternatives, I'd like to clarify that I'm looking for a definition which is valid for both C and C++, all flavours etc.
According to this answer by user GMan the typical way is to cast to void:
#define UNUSED(x) (void)(x)
but if x is marked as volatile that would enforce reading from the variable and thus have a side effect and so the actual way to almost guarantee a no-op and suppress the compiler warning is the following:
// use expression as sub-expression,
// then make type of full expression int, discard result
#define UNUSED(x) (void)(sizeof((x), 0))
In C++, just comment out the names.
void MyFunction(int /* name_of_arg1 */, float /* name_of_arg2*/)
{
...
}
The universal way is not to turn on warnings options that spam warnings for clearly-correct code. Any "unused variable" warning option that includes function arguments in its analysis is simply wrong and should be left off. Don't litter your code with ugliness to quiet broken compilers.
You might also try sending a bug report to the compiler maintainer/vendor.