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