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

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.

Related

What conditional compilation is needed around C++ attributes?

I'm starting to add [[nodiscard]], [[noreturn]] and [[fallthrough]] to my code base, but I still worry the code might need to be used on an older C++ version.
I'm only worried about g++, clang, and Visual Studio.
To be safe should I make every single usage depend on a version check for the exact version it appeared? Or, do these compilers accept (or does the spec even mandate they accept) any [[attribute]] even if unknown, starting with C++11?
Were these allowed and ignored (or supported) even before C++11? (I ask not what the spec says but what the software actually did.)
#if __cplusplus >= 201703L
#define MyNamespace_NoReturnCPP17 [[noreturn]]
#else
#define MyNamespace_NoReturnCPP17
#endif
(Off subject but if I were on the C++ committee, I'd re-use the case keyword to do the same thing as switch, when followed by (, except it would in effect have an automatic break before each case label. And within the case's block (and nowhere else), fallthrough would be accepted as a keyword, that suppresses that automatic break.)
I note the C++14 spec 7.6.1.5 says behavior is "implemenation-defined" but I'm asking a more practical question about what compilers actually did. https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4296.pdf
The C++17 spec 10.6.1.6 says "Any attribute-token that is not recognized by the implementation is ignored." That answers my question for C++17 and newer, but again my question is about earlier compilers. https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/n4713.pdf
To be safe should I make every single usage depend on a version check for the exact version it appeared? Or, do these compilers accept (or does the spec even mandate they accept) any [[attribute]] even if unknown, starting with C++11?
I prefer adding version checks for safety although mainstream compilers will throw a warning for unknown attributes.
gcc -Wno-ignored-attributes / -Wattributes
Clang -Wunknown-attributes
MSVC C5030
I'm not sure these warning options(and corresponding behavior) have been added since the first C++11 feature-complete version, so you'd better do some checks.
Were these allowed and ignored (or supported) even before C++11?
Since standard attributes syntax is supported starting from C++11, compilers will have trouble at the parsing stage. Demo

(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.

Difference in the style of giving comments between C and C++

Is there any difference between a commenting style between C(/*..*/) and C++(//)?
MISRA C:2004 says
Rule 2.2 (required): Source code shall only use /* … */ style
comments.
Note: This Rule is revoked for MISRA C:2012 when support for C99 was added
MISRA C++ says
Rule 2.7.1 (required): The character sequence /* shall not be used
with c style comments.
Rule 2.7.3 says suggested comment as // for c++
Can any one explain why MISRA says to use /* in C and // in C++?
The MISRA C clause you quote requires that "line comments" of the form
// This is a line comment
not be used, in favour of a "C-style" comment of the form
/* Original C style comment
Can extend across multiple lines
*/
This allows older compilers to be used, since the "line comment" was only introduced in 1999, and was only available with some compilers before then as a non-standard extension.
The MISRA C++ clause you quote (from memory, there is a similar one in MISRA C) requires that the "original C-style comment" shall not be nested. So, this is discouraged
/* Warning: non-standard nesting of comment
/* Nested comment
*/
*/
This is discouraged because support for it is not standard, but some compilers can be configured to support it. Code which uses "nested comments" can therefore behave differently (including compiling with one compiler, but not with another) and in unintended ways. However, code without nested comments will compile as intended, regardless of whether or not the compiler supports nested comments.
There isn't a problem with nesting of "line comments", since the // causes the compiler to ignore everything to end of line. This is okay in C++, since (unlike C) all C++ versions (even pre-standard) support "line comments". (This is not necessarily true if digraphs or trigraphs are used, but MISRA also discourages using them).
Rule 2.2 means C only allows /**/ comments, while rules 2.7.1 tells not to nest C comments, by forbidding the use /* in a C comment. They are unrelated.
C89 had only /* ... */ for comments. But C++ style comments // .. were added to C in C99. I think MISRA simply attempts to keep it consistent so that the C++ style comments do not become an issue if you are compiling the C code in C89/C90.
But this rarely matters anymore as both styles of comments are supported in both modern C and C++.
You can read the MISRA rationale for the reasoning:
MISRA-C-2004 rationale:
Rule 2.3 (required): The character sequence /* shall not be used
within a comment.
C does not support the nesting of comments even though some compilers
support this as a language extension. A comment begins with /*
and continues until the first */ is encountered. Any /* occurring
inside a comment is a violation of this rule.
Consider the following code fragment: /* some comment, end comment
marker accidentally omitted <>
Perform_Critical_Safety_Function(X); /* this comment is not compliant
*/
In reviewing the page containing the call to the function, the
assumption is that it is executed code. Because of the accidental
omission of the end comment marker, the call to the safety
critical function will not be executed.
MISRA-C++ 2008 rationale:
Rule 2-7-1 The character sequence /* shall not be used within a
C-style comment.
C++ does not support the nesting of C-style comments even though some
compilers support this as a non-portable language extension. A comment
beginning with /* continues until the first */ is encountered. Any
/* occurring inside a comment is a violation of this rule.
Although // were an incredibly common non-standard extension to C90 compilers, it was never allowed by the C90 standard. The rationale for the MISRA rule is that you should follow the applicable language standard.
So it's quite simple:
MISRA-C:2004 is for C90 which only allowed /* */ comments.
MISRA-C++:2008 is for C++, which allows // comments (no matter C++ version)
MISRA-C:2012 is for C99 which allows // comments.
Because of the above, the rule you refer to has been removed in MISRA-C:2012. Consider upgrading to the 2012 MISRA version, as it has been improved in many ways.
In short, those standards are to help the programmers from getting inconsistent compiler behaviors due to the comment style when they compile their codes using different compiler standards.
This is the rationale behind the standards.
More elaborated answer:
This is because the // line comment is not supported before C99 standard. While MISRA-C 2004 document is created to support C89/C90 standard.
Rule 2.2 (required): Source code shall only use /* … */ style
comments.
This excludes the use of // C99 style comments and C++ style
comments, since these are not permitted in C90. Many compilers support
the // style of comments as an extension to C90. The use of // in
preprocessor directives (e.g. #define) can vary. Also the mixing of /*
… */ and // is not consistent. This is more than a style issue, since
different (pre C99) compilers may behave differently
Check Lundin's answer on this post. Also, check this SO post on C line commenting before C99.
Thus, that explain why the MISRA-C 2004 clause you post requires /* to be used.
With the same idea, the MISRA-C++ 2008 standard discourages the use of /* - C-Style (multiline) comment - in C++ since some compilers may generate errors. It encourages to use // since it is the "original" C++ comment style.
From MISRA C 2004:
Rule 2.2 (required): Source code shall only use /* … */ style comments.
This excludes the use of // C99 style comments and C++ style comments, since these are not
permitted in C90. Many compilers support the // style of comments as an extension to C90. The
use of // in preprocessor directives (e.g. #define) can vary. Also the mixing of /* … */ and //
is not consistent. This is more than a style issue, since different (pre C99) compilers may behave differently.
I think this explains it all, but I'll still add my explanation with links.
In original C (pre C99), there were no // comments. C++ introduced a double slash comment prefix // as a way to comment single lines.
For more clarity, let's go line by line:
This excludes the use of // C99 style comments and C++ style comments, since these are not
permitted in C90.
Nowadays, modern compilers like gcc have started supporting such // in C90 mode also, but will still issue a warning like:
warning: C++ style comments are not allowed in C90
but it is recommended to use /*..*/ comments in C90 C.
Many compilers support the // style of comments as an extension to C90.
That is what I exactly told above, but it is still not recommended to use // in C90 C as the code will not be portable. For example, that code will compile with gcc, but with another compiler which does not have the extension, it will not compile.
The
use of // in preprocessor directives (e.g. #define) can vary.
I think the meaning of this is clear. It says that the usage of // is not going to be consistent in preprocessor directives.
Also the mixing of /* ... */ and //
is not consistent.
How? This is possible. Like I mentioned above, it varies from compiler to compiler. In C99 C, it will be mostly consistent, but if you're talking about the pre C99 compilers, it matters if they support or not support // comments.
This is more than a style issue, since different (pre C99) compilers may behave differently.
Yes it is. As this is MISRA 2004, which is mainly talking about pre C90 C mainly. This is because most C90 compilers do not support //, and thus you will get an error. If you're using C99, this is invalid.
Questions Expected
Why was there no // in pre C99 C, and then why was it introduced in C++? Is there a specific reason?
C originated from B. B originated from BCPL. // were created during BCPL, and thus BCPl used them. It's successor B started using /*...*/, which were inherited by C. Although, C++ decided to resurrect the BCPL comments, and of course used /*...*/ also. The C-standard at that time took // as a non-standard feature.
When C99 C was introduced, it had the comments //.
What are // and /*...*/ comments called?
// comments are called single-line comments as they can only extend till one line.
/*...*/ comments are called multi-line comments as they can extend upto multiple lines.
Is it compulsory to use only one kind of comment through your source code?
No, you can use any and even both. Although, some people say that using only one type makes the code readable. It is more a matter of opinion.
Is rule 2.2 of MISRA C 2004 outdated?
Kind of. Recently, MISRA 2012 was released which has these changes. Although, if you think that MISRA C 2004 is wrong as it is only concentrating on pre C99, it isn't. I would recommend using MISRA 2012 nowadays.
Rule 2.7.1 (required): The character sequence /* shall not be used with c style comments.
(emphasis added)
I think you are just misreading the meaning of the word "with" in the above rule and interpreting in the sense "shall not be used for c style comments".
Perhaps the rule would be more clear if the word "within" were used rather than "with".

Diagnostic message for well-formed program

Is an implementation allowed to issue a diagnostic message for a well-formed program?
For example some compilers issue a warning about unused expression result when compiling the following well-formed program:
int main() { 0; }
Are such compilers allowed to consider that warning a diagnostic message?
It's perfectly fine to issue a diagnostic, as long as the rules below are met in any corresponding scenario. §1.4/2:
Although this International Standard states only requirements on C ++
implementations, those requirements are often easier to understand if
they are phrased as requirements on programs, parts of programs, or
execution of programs. Such requirements have the following meaning:
If a program contains no violations of the rules in this International Standard, a conforming implementation shall, within
its resource limits, accept and correctly execute that program.
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.
If a program contains a violation of a rule for which no diagnostic is required, this International Standard places no requirement on
implementations with respect to that program.
"Accepting" solely addresses the acknowledgment of the implementation that this is a well-formed program, not the absence of any diagnostics. After all, despite any warnings issued in the process, implementations still yield the object file you asked for.
However, there is one rule concerning templates that does require that there be no diagnostic issued; §14.6/8:
No diagnostic shall be issued for a template for which a valid
specialization can be generated.
An implementation can issue (1)any number of diagnostics it wants, as long as it does issue the required diagnostics.
It must accept correct programs, to the degree that it's able to,
C++14 §1.4/2:
” If a program contains no violations of the rules in this International Standard, a conforming imple-
mentation shall, within its resource limits, accept and correctly execute that program"
but it can issue diagnostics about it.
The C++ standard does not differentiate between error messages and warning messages, but this is a de facto standard. An error message means (by convention) that no binary is produced, because the problem is too severe. A warning message means (by convention) that there is a potential problem, but not a direct violation of language rules, and so a binary is produced unless there are also errors.
Sometimes the lines are a bit blurred, where implementations incorrectly but for pragmatic reasons accept invalid code, with only warnings or even no diagnostics. For new code one may therefore ask the compiler to treat every warning as an error, and aim for completely clean compiles. And as I understand it that's now absolutely not uncommon.
With some compilers, e.g. Visual C++, it can however be problematic, because the compiler issues too many silly-warnings, warnings about perfectly legitimate and non-problematic constructs. Then one has to somehow suppress those warnings. E.g. via #pragma directives, if possible, or by code rewrites.
Happily for Visual C++ there exists a header with such #pragma directives that turn off sillywarnings, compiled about five years ago from a community effort in the comp.lang.c++ Usenet group. And happily, for the community edition of Visual Studio 2015 there is an extension that provides a project template with that header included. These are both by me.
For the code in question,
int main() { 0; }
… instead of suppressing the warning, which generally is a useful one, you should rewrite the code to express your intent explicitly:
int main() { (void)0; }
The (void) cast tells the compiler that it's your intent to discard the value of that expression.
In the case of using this construct for an otherwise unused function argument, you can additionally declare an incomplete class of the same name, to prevent inadvertent use of the name:
(void)arg_name; struct arg_name;
But since it's unconventional it may trip up other programmers – with the compilers I use the error message for later use of the name is not exactly intuitive.
(1) Except as noted by Columbo in his answer, C++14 §14.6/8 “No diagnostic shall be issued for a template for which a valid specialization can be generated.”.

Compiler chosing prefix ++ when postfix is missing - who says?

When you define a prefix operator++ for your user defined type and you don't provide a postfix version, the compiler (in Visual C++ at least) will use the PREFIX version when your code calls the missing POSTFIX version.
At least it will give you a warning. But, my question is: Why doesn't it just give you an error for the undefined member function?
I have seen this first hand, and have seen it mentioned in another post and elsewhere, but I cannot find this in the actual C++ standard. My second and third questions are... Is it in the standard somewhere? Is this a Microsoft-specific handing of the situation?
Actually, In this case the MSVC behaves much more intelligently than GCC.
This is a MSVC compiler extension and the C++ standard explicitly allows for such an behavior.
C++ Standard:
Section 1.4/8:
A conforming implementation may have extensions (including additional library functions), provided they do not alter the behavior of any well-formed program. Implementations are required to diagnose programs that use such extensions that are ill-formed according to this International Standard. Having done so, however, they can compile and execute such programs.
In this case, MSVC appropriately diagnoses the problem that the postfix is not available and it specifically defines warnings,
Compiler Warning (level 1) C4620
Compiler Warning (level 1) C4621
Also, it provides you a facility to disable the MSVC specific extensions by using /Za. Overall, I would say this is one of the instances where MSVC actually behaves better than GCC.
It should be a Microsoft specific extension. Because, at least g++ is strict about prefix and postfix operators. Here is the demo link.
With integers, ++i is different from i++. For exampe i=5, y = ++i - y will be 6; y=i++ - y will be 5. Other types should function in the same manner. Therefore the behaviour differs between postfix and prefix.
It is a Microsoft thing and in my opinion the compilers implementation is incorrect.