It is perfectly valid code, so the compiler does not have to issue a diagnostic although having a diagnostic would be helpful in this case. This is one of the reasons many developers prefer clang
since they tend to go above what is required when it comes to diagnostic.
For the standards rules on diagnostic messages, we can go to the draft C++ standard section 1.4
Implementation compliance which says (emphasis mine):
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.”
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 execute2 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.
No syntactic or semantic rules are violated by this program and so no diagnostic is required.
We have the following code:
if (some_condition) (p1, p2, color);
^ ^ ^
1 2 3
1
is an expression-statement which is valid in this context for and if statement. We can see this by going to the grammar:
if ( condition ) statement
and:
statement:
attribute-specifier-seqopt expression-statement
and:
expression-statement:
expressionopt;
and:
primary-expression:
( expression )
Both 2
and 3
are the comma operator which will evaluate the left operand and discard the value and then evaluate the right operand again nothing invalid here.
So what does section 5.18
Comma operator says:
A pair of expressions separated by a comma is evaluated left-to-right;
the left expression is a discarded value expression (Clause 5).83
and a discarded value expression is covered in section 5
which says:
In some contexts, an expression only appears for its side effects.
Such an expression is called a discarded-value expression.
So since the value of the result of the left hand expression is discarded then we must only care about the side-effect. In your specific case evaluating the variable has no other effect besides generating a value hence the warning, but if you had used a function in their place e.g.:
bool func()
{
//...
}
and change your code to:
if (some_condition) (func(), func(), func() );
neither clang
nor gcc
will provide a warning since presumably func
will perform some side-effet that you care about.