Issue warning and compiling with warnings-as-errors violates compliance? - c++

My question (Single line comment continuation) got me wondering about compiler compliance and warning messages, particularly with warnings-as-error feature in many compilers.
From the C++ spec, § 1.4.2.1 states:
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 warning message is issued for code which technically conforms to the standard (as in my linked question), even if I specifically asked for a warning to be issued (again, in my example if I used -Wcomments with gcc), and I use warning-as-errors (-Werror), the program will not compile. I realize that this is rather obtuse, given that I could workaround the issue in several ways. However, given the quote, is this a violation of the standard which is generally permitted, or is somehow otherwise explicitly allowed?

Yes, if you tell the implementation not to conform with the standard (for example, by requesting errors for well-formed code constructs), then its behaviour won't be conforming.

Related

Are compilers allowed to support a feature, that is removed in the standard?

In the first paragraph cppreference.com clearly states that throw(T1, ..., Tn) is removed in C++17.
It confuses me, that some compilers support throw(T1, ..., Tn) in C++17 mode (see demo).
MSVC supports it by default, but you can turn on a warning for it, see C5040. It can be turned into an error with /we5040.
Clang reports it as an error by default, but the error can be turned off with -Wno-dynamic-exception-spec.
GCC leaves you with no choice: it's an error.
Are compilers allowed to support a feature, that is removed in the standard? For what purpose?
Or is this just a compiler extension, like void foo(int size) { char a[size]; } in GCC, see demo.
Are compilers allowed to support a feature, that is removed in the standard?
The standard doesn't allow that. AFAIK in general it doesn't give any special treatment to features that used to be in the language (doesn't separate them from non-existent features).
If a compiler doesn't diagnose this error (i.e. doesn't give an error or a warning) with a specific configuration (i.e. specific flags), then it doesn't conform to the standard in that configuration.
For what purpose?
Backward compatibility (what else could it be). More specifically, it lets you use both old and new features in a same translation unit.
This can be useful if you're using a library that uses a removed feature in its headers, but want to use the new language features in your own code.
Or if you want to use the removed feature in your own code along with the new features, for some reason.
Note that absolute conformance to the standard is not practically possible to achieve.
Some compiler vendors care about conformance more than the others. Microsoft tends to care less about it (or at least used to, they've been working on that).
There is no single answer for this.
Some things outside the Standard can be treated as pure enhancements. Some of these enhancements are suggested by the Standard ("It's implementation-dependent if X"), some are not even mentioned at all (#include <windows.h>).
For other things, the Standard does require that a compiler flags the violation of the Standard. But the Standard doesn't talk about errors or warnings. Instead it says "Diagnostic Required", which is understood to mean either an error or a warning. And in other cases it even says "No Diagnostic Required" (NDR), which means the compiler is not obliged to flag non-standard code.
So depending on the removed feature, it may or may not require a diagnostic. And if it does require a diagnostic, you can often tell the compiler that you're not interested in that particular diagnostic anyway.
Are compilers allowed to support a feature, that is removed in the standard? For what purpose?
Compilers can do whatever they want. The C++ standard dictates rules for the C++ language, and while they do consult compiler vendors to ensure its rules are implementable, the vendors themselves will do what they feel is best for them and their users. Compilers have many non-standard features that developers use all the time. And I don't think any of these compilers fully adhere to the standard by default.
That said, I wouldn't call a compiler+settings "C++17 compliant" if they allowed non-C++17 code or rejected valid C++17 code (as dictated by the standard). Most compilers have settings that can be set if full compliance is desired.
If you want to be pedantic though MSVC isn't even C++11 compliant due to lacking preprocessor. The standard isn't everything.

In the C++ standard does well-formed means that the code compiles?

The C++ standards defines well-formed programs as
C ++ program constructed according to the syntax rules, diagnosable
semantic rules, and the one-definition rule
I am wondering if all well-formed program compile or not (if it is not the case, what types of error make the difference between a well-formed program and a compilable problem). For example would a program containing ambiguity errors considered as well-formed?
A well-formed program can have undefined behaviour.
It's in a note, and thus not technically authoritative, but it seems that it is intention that termination of compilation (or "translation" as the standard calls it) is within the scope of possible UB:
[intro.defs]
undefined behavior
behavior for which this document imposes no requirements
[ Note: Undefined behavior may be expected when this document omits any explicit definition of behavior or when a program uses an erroneous construct or erroneous data.
Permissible undefined behavior ranges from ignoring the situation completely with unpredictable results, to behaving during translation or program execution in a documented manner characteristic of the environment (with or without the issuance of a diagnostic message), to terminating a translation or execution (with the issuance of a diagnostic message).
Many erroneous program constructs do not engender undefined behavior; they are required to be diagnosed.
Evaluation of a constant expression never exhibits behavior explicitly specified as undefined in [intro] through [cpp] of this document ([expr.const]).
— end note
]
There are also practical implementation limits:
[implemits]
Because computers are finite, C++ implementations are inevitably limited in the size of the programs they can successfully process.
Every implementation shall document those limitations where known. This documentation may cite fixed limits where they exist, say how to compute variable limits as a function of available resources, or say that fixed limits do not exist or are unknown.
Furthermore, compilers can have, and do have bugs. Well-formed simply means the a standard conforming compiler should compile it (within the limitations mentioned above). A buggy compiler does not necessarily conform to the standard.
Lastly, the standard document itself is not perfect. If there is disagreement about what the rules mean, then it is possible for a program to be well-formed under one interpretation, and ill-formed under another interpretation.
If a compiler disagrees with the programmer or another compiler, then it might fail to compile a program that is believed to be well-formed by the other party.
I am wondering if all well-formed programs compile or not
Of course not, in practice.
A typical example is when you ask for optimizations on a huge translation unit containing long C++ functions.
(but in theory, yes)
See of course the n3337 C++11 standard, or the C++17 standard.
This happened to me in the (old) GCC MELT project. I was generating C++ code compiled by GCC, basically using transpiler (or source to source compilation) techniques on Lispy DSL of my invention to generate the C++ code of GCC plugins. See also this and that.
In practice, if you generate a single C++ function of a hundred thousand statements, the compiler has trouble in optimizing it.
Large generated C++ functions are possible in GUI code generators (e.g. FLUID), or with some parser generators such as ANTLR (when the underlying input grammar is badly designed), interface generators such as SWIG, or by using preprocessors such as GPP or GNU m4 (like GNU autoconf does). C++ template expansion may also produce arbitrarily large functions (e.g. when you combine several C++ container templates and ask the GCC compiler to optimize at link-time with g++ -flto -O2)
I did benchmark, and experimentally observed in the previous decade that compiling a C++ function of n statements may take O(n2) time (and IIRC O(n log n) space) with g++ -O3. Notice that a good optimizing C++ compiler has to do register allocation, loop unrolling, inline expansion, that some ABIs (including on Linux/x86-64) mandate passing or returning small struct-s (or instances of small class-s) thru registers. All these optimizations require trade-offs and are hitting some combinatorial explosion wall: in practice, compiler optimization is at least an intractable problem, and probably an undecidable one. See also the related Rice's theorem and read the Dragon Book.
You could adapt my manydl.c program (generating more or less random C code compiled as several plugins then dlopen-ing them on Linux) to emit C++. You'll then be able to do some GCC compiler benchmarks, since that manydl program is able to generate hundred thousands plugins containing lots of more or less random C functions. See Drepper's paper how to write shared libraries and be aware of libgccjit.
See also the blog of the late Jacques Pitrat (1934-oct.2019) for an example of a C program generating the half millions lines of its own C code, whose design is explained in this paper and that book.
Read Thriving in a crowded and changing world: C++ 2006--2020

C++ code compiles differently on different OS

I was wondering so why does c++ code compile differently on different version of the OS. Such as when the same code is complied on the OS no warning or anything will be brought up, but when the same code is complied on a different OS, there will be warnings or errors.
So why does this happen. Is the difference between gcc versions or what actually makes the c++ code unique when its complied on two different OS such Ubuntu 14 and Ubuntu 16. I am just trying to understand how the c++ code is unique to the OS compilation.
C++ as a language is defined by its standard. The standard is an enormous, lawyer-lingo document that defines the language's syntax, rules, standard library, and some guidelines for how compilers should correctly process source code. Compilers, the bridge between the abstract language and real, executable programs, are implemented by different vendors or organizations, and should adhere to that standard as closely as possible. In practice, their correctness varies[1].
Many compiler errors are part of the standard (diagnostics in standardese), and so should in principle be essentially the same across compilers[2]. Compiler warnings generally are less technical, and are often ways that compiler vendors try to help you catch common programming errors that aren't technically ill-formed programs. A program may be ill-formed according to the standard, meaning that it is syntactically invalid and does not represent a real program. Compilers are required by the standard to issue a diagnostic for an ill-formed program.
There are however lesser, more subtle ways that programs can be incorrect though, for example by using what the standard refers to as undefined behavior (UB) and implementation-defined behavior. These are situations where the standard doesn't specify how a compiler should correctly translate source code into a program, and compiler vendors are legally allowed to proceed how they please. While many compilers are likely to produce code that does approximately what you expect it to, invoking undefined behavior in a program is generally a very bad idea because there's no guarantee of any kind how your program will behave. Code with UB that compiles quietly and passes tests on one compiler may fail tests or fail to compile altogether, or encounter a bug at the worst possible time, on a different compiler. The situation gets hairy too if you're using compiler-specific language extensions.
When faced with potential UB, some compilers may offer very helpful advice and others may be misleadingly silent. The best practice would be to be familiar with causes of UB by learning C++ from a good source and reading documentation carefully, both C++ language documentation and that of any libraries you may be using.
[1] Take a look at the 'Standard conformance' columns of the list of C++ compilers at https://en.wikipedia.org/wiki/List_of_compilers#C++_compilers
[2] A comparison of error messages and warnings from three very popular compilers: https://easyaspi314.github.io/gcc-vs-clang.html

Implementation defined between versions

Is it mandatory that compilers keep the behavior consistent between versions of what the C or C++ standard describes as implementation-defined behavior?
For example the result of some bitwise operations on signed integers must be the same in gcc 4.6 and say in gcc 4.8?
It does not have to be consistent, it just needs to be documented, the draft C99 standard section 3 Terms, definitions, and symbols defines it like so:
implementation-defined behavior
unspecified behavior where each implementation documents how the choice is made
For example the gcc docs has a section C Implementation-defined behavior.
The C++ draft standard also has a similar definition and in section 1.9 Program execution paragraph 2 says:
Certain aspects and operations of the abstract machine are described in this International Standard as implementation-defined (for example, sizeof(int)). These constitute the parameters of the abstract machine. Each implementation shall include documentation describing its characteristics and behavior in these respects.6[...]
No.
The C standard mandates some things. For the ones which are implementation-defined, it does not mandate that you are consistent between versions.
This would not be very useful anyway - what stops you to create "Extra Gcc" instead of "gcc 5"? Who determines what version is actually an upgrade from a previous one?
Implementation defined means that the compiler writer chooses what happens, and that is just it. There's nothing stopping you from changing your mind and do it another way of you want. Nothing forces you to be consistent among different versions of the same compiler.
From the standpoint of the C standard, two versions of the "same" compiler are two different implementations. (Well, it's likely that the earlier is known not to be a C implementation at all due to known conformance errors, and the latter is also likely not to be a C implementation due to unknown conformance errors...) In general, implementors will provide their own guarantees that implementation-defined behavior will remain the same between versions, however. This is because they have already defined the behavior, and if they change it, they're creating an explicit incompatibility with something they already documented as behavior you could rely upon with their product.

Is gets() officially deprecated? [duplicate]

This question already has answers here:
Why is the gets function so dangerous that it should not be used?
(13 answers)
Closed 1 year ago.
Based on the most recent draft of C++11, C++ refers to ISO/IEC 9899:1999/Cor.3:2007(E) for the definitions of the C library functions (per §1.2[intro.refs]/1).
Based on the most recent draft of C99 TC3, The gets function is obsolescent, and is deprecated. (per §7.26.9/2)
Can I safely say that gets() is deprecated in both C and C++?
Deprecated means you shouldn't use it and it might be removed in the future. Since both standards say it is deprecated, that means it is deprecated, officially.
Does it matter? The only way you can ever use gets is if stdin is known to be attached to a file whose contents you have full control over. This condition is almost impossible to satisfy, especially on multiprocess systems where other processes may modify files asynchronously with respect to your program. Therefore, for all practical purposes, any program using gets has undefined behavior (i.e. there are possible inputs/environmental conditions for which it will have undefined behavior), and in particular UB which is likely to lead to privilege compromise if your program has higher privileges than the provider of the data.
Edit: OK, here's one safe use of gets, about the only one I can think of right off...
if (feof(stdin)) gets(buf);
Of course some buggy implementations (possibly including glibc..?) permit reads even when the EOF indicator is already set for a stream, so....
Even code which would be broken by the removal of gets() from the library would, after such removal, be less broken than it was before such removal. I suppose it might be necessary for compiler vendors to include it in a "fully-standard compliant" mode, but the number of circumstances where it could safely be used is so vanishingly small that it would probably be reasonable to exclude it from a "normal" build.
It's going to be a while until C++11 is implemented everywhere.
Also, most compilers doesn't even fully support C99 yet.
Microsoft's, for instance, does not.
So no, it's not deprecated in both C and C++.
Well it was removed altogether from the C11 standard, so I'd take that as a yes.