Is it standard-compliant to compile ill-formed program in success? - c++

For an ill-formed C++ program like:
foo^##$bar%$
Is it standard-compliant for compiler to yield compiled binary with diagnostic message, rather than interrupting the compilation as g++/clang++ do?
intro.compliance states that:
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.
which does not require compilation error in this case.
Possibly related:
What is the C++ compiler required to do with ill-formed programs according to the Standard?
Ill-Formed, No Diagnostic Required (NDR): ConstExpr Function Throw in C++14

Yes, it is legal for the implementation to produce a binary when the input is an ill-formed program. Here is [intro.compliance]/8 in C++14:
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 such cases the diagnostic would usually be referred to as a "warning" (as opposed to "error").

Related

Why is calling the main function supposedly undefined behavior (UB)

I fear this is again a question about interpreting the ISO/IEC 14882 (the C++ standard) but:
Is calling main from the program e.g. my calling main() recursively from main not at least implementation defined behavior? (Update: I imply later ill-formed not implementation defined, also not UB, see below and answer)
6.9.3.1 [basic.start.main] states
3 The function main shall not be used within a program. The linkage (6.6) of main is implementation-defined...
The consensus seems to be undefined behavior (UB). The documentation of MSVC also points towards UB, the one of gcc also implicitly denies implementation-defined behavior. It can not be [defns.unspecified] unspecified behavior since I would interpret shall not as ill-formed.
However, despite the implementations, to my interpretation is should not be UB but as 4.1 [intro.compliance] states
1 The set of diagnosable rules consists of all syntactic and semantic rules in this document except for those
rules containing an explicit notation that “no diagnostic is required” or which are described as resulting in
“undefined behavior”.
...
(2.2) — If a program contains a violation of any diagnosable rule or an occurrence of a construct described in
this document as “conditionally-supported” when the implementation does not support that construct,
a conforming implementation shall issue at least one diagnostic message.
For me the reasoning seems clear
tl;dr
calling main implies the program contains a violation of the rule of [basic.start.main]
[basic.start.main] does not state calling/use is UB or a diagnostic is not required
is an element of "diagnosable rules" as per [intro.compliance]
[intro.compliance] 2.2 states violation of any diagnoseable rule must be issued at least one diagnostic message
Since 3. and 4. the usage of main shall issue at least one diagnostic message
Since 5. 1. is not UB
Since neither gcc,MSVC or clang issue an error or warning but compile, all major implementations are not compliant
Of course since 7. I feel again in the Don Quixote scenario i.e. being wrong, so I would appreciate if someone could enlighten me about my mistake. Otherwise, there are standard defects, aren't there?
I think your analysis is correct: calls to main are ill-formed.
You have to pass the -pedantic flag to make GCC and Clang conform. In that case, Clang says
warning: ISO C++ does not allow 'main' to be used by a program [-Wmain]
and GCC says
warning: ISO C++ forbids taking address of function '::main' [-Wpedantic]
But they allow calls to main as an extension. The standard permits such an extension, since it doesn't change the meaning of any conforming programs.

Do "mandates" conditions in the C++ standard always result in an error? [duplicate]

C++03 Standard defines well-formed program (1.3.14 [defns.well.formed]) as
a C++ program constructed according to the syntax rules, diagnosable semantic rules, and the One Definition Rule (3.2)
It further defines an ill-formed program (1.3.4 [defns.ill.formed]) as
input to a C++ implementation that is not a well-formed program (1.3.14)
and the Standard is full of statements such as "if X then the program is ill-formed" for example (2.13.1/3):
A program is ill-formed if one of its translation units contains an integer literal that cannot be represented by any of the allowed types.
Yet I haven't found what the C++ implementation is required to do with ill-formed programs.
Suppose I have an ill-formed program. Now what?
Is the C++ implementation required to do something specific when it encounters an ill-formed program or is the C++ implementation behavior just undefined?
Is the C++ implementation required to do something specific when it encounters an ill-formed program or is the C++ implementation behavior just undefined?
If the Standard does not specify otherwise, an implementation should emit a diagnostic message (error or warning). However, for some violations the Standard explicitly specifies that no diagnostic is required. In this case, the program is ill-formed, but implementations are not required to tell the user - usually, because doing so in the general case would be too difficult.
Concerning the One Definition Rule, for example, see Paragraph 3.2/4 of the C++11 Standard:
Every program shall contain exactly one definition of every non-inline function or variable that is odr-used
in that program; no diagnostic required.
Regarding the requirements on implementations when encountering a violation of a rule, Paragraph 1.4/2 specifies:
[...]
— 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.
Also relevant is Paragraph 1.4/1, which explains what is meant by "diagnosable rules" in the Paragraph quoted above:
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.”
So to sum it up: if an ill-formed program contains a diagnosable violation for which the Standard does not explicitly specify "no diagnostic required", conforming implementations should emit a diagnostic.
Quoting [intro.compliance]§2:
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.
I haven't found any other relevant passages in the standard. If we combine this with [defns.undefined]:
undefined behavior
behavior for which this International Standard imposes no requirements
[ Note: Undefined behavior may be expected when this International
Standard 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. -end note ]
I'd say we arrive at "issue a diagnostic message and further the behaviour is undefined," because the standard doesn't say anything more about it.
(First of all, sorry for my English)
The Standard, in §1.4.2 says:
If a program contains a violation of any diagnosable rule [...] a conforming implementation shall issue at least one diagnostic message.
The definition of a ill-formed program is "a program that is not well formed" (§1.3.9), and a well-formed program is (§1.3.26):
C++ program constructed according to the syntax rules, diagnosable semantic rules, and the One Definition Rule
So, a ill-formed program does implicitly violate "some" rule. If a rule R has the following structure:
If a program has property P, it is an ill-formed program.
When a program has such property P, it does implicitly violate a rule (by definition of an ill-formed program), although it isn't clear which rule is the one which are being violated, since R itself doesn't (from a strictly logical point of view).
The only relevant quote I could find says that an implementation is required to diagnose an ill-formed program, but it can finish compiling it:
1.4 Implementation compliance [intro.compliance]
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.

Why does [[nodiscard]] only encourage compiler to issue a warning and does not require it?

The [[nodiscard]] attribute introduced in C++17 standard, and in case of the
... potentially-evaluated discarded-value expression,..., implementations are encouraged to issue a warning in such cases.
Source: n4659, C++17 final working draft.
Similar phrasing is used on cppreference, that in case of "violation":
the compiler is encouraged to issue a warning.
Why is the word encouraged used instead of required? Are there situations (except, the explicit cast to void) when a compiler is better off not issuing a warning? What is the reason behind softening the standard language in the particular case of relatively safe requirement to issue a warning no matter what (again, except, say, explicit cast to void)?
The C++ standard specifies the behavior of a valid C++ program. In so doing, it also defines what "valid C++ program" means.
Diagnostics are only required for code which is ill-formed, code which is syntactically or semantically incorrect (and even then, there are some ill-formed circumstances that don't require diagnostics). Either the code is well-formed, or it is ill-formed and (usually) a diagnostic is displayed.
So the very idea of a "warning" is just not something the C++ standard recognizes, or is meant to recognize. Notice that even the "implementations are encouraged to issue a warning" statement is in a non-normative notation, rather than a legitimate specification of behavior.

Which guarantees does the C++ standard have when it comes to issuing diagnostic messages?

While reading the C++ standard, one often sees designations like "... ill-formed, no diagnostic required". A (random) example can be found in 13.8.1/17:
The class S1::Inner1 is ill-formed, no diagnostic required, because
it has no valid specializations.
Where can one find an opposite normative language in the standard, which would prescribe a diagnostic for an ill-formed program?
What you are looking for is [intro.compliance]/1
The set of diagnosable rules consists of all syntactic and semantic rules in this document except for those rules containing an explicit notation that “no diagnostic is required” or which are described as resulting in “undefined behavior”.
It is then followed up with [intro.compliance]/2
If a program contains a violation of any diagnosable rule or an occurrence of a construct described in this document as “conditionally-supported” when the implementation does not support that construct, a conforming implementation shall issue at least one diagnostic message.
which guarantees that if you break one of the diagnosable rules you'll get a diagnostic message.

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