.ds RH Multi-condition Coverage
.bp
.sp
.NH 1
Multi-condition Coverage
.XS
   Multi-condition Coverage
.XE
.LP
For the following operators, both the left-hand and right-hand
sides must be both zero and non-zero:
.TS
center allbox tab(#) ;
c c 
l l .
Operator # Point of instrumentation
logical and#&&
logical or#||
.TE
.LP
\fBgreport\fR reports on each half of each condition separately.  For a line
of code like
.nf

     if (a && (b < 12 || b > c))

.fi
\fBgreport\fR output would look like:
.nf

"test.c", line 4: condition 1 (a, 1) was taken TRUE 1, FALSE 0 times.
"test.c", line 4: condition 2 (b, 1) was taken TRUE 1, FALSE 0 times.
"test.c", line 4: condition 3 (b, 2) was taken TRUE 1, FALSE 0 times.
"test.c", line 4: condition 4 (b, 2) was taken TRUE 0, FALSE 0 times.

.fi
The condition number identifies the condition in the line, numbered
from left to right.  The items in parentheses make it easier to find
the condition.  The first item is the first token in one of the sides
of the logical expression.
The second item is the nesting level in the tree of boolean
operators that makes up the whole expression.  Thus, in the above
example, we have these conditions:
.nf

1 	a 			(&&-expression, left side)
2	(b < 12 || c > c)	(&&-expression, right side)
3	b<12			(||-expression, left side)
4	b>c			(||-expression, right side)

.fi
.LP
Another test condition that has proven useful
is to insist that a function that returns a boolean value should
return both zero and non-zero.  Since C has no boolean
type, GCT must deduce when a particular integer-returning function
really returns boolean values.  This is done by considering the expression
that calculates the return value:
.nf

	return 1 + 1;		/* Returns integer. */
	return a && b;		/* Returns boolean. */
	return f(a);		/* We don't know. */

.fi
Here are the operators that produce boolean return values:
.TS
center box tab(#) ;
l l l l l l l .
<#<=#>#>=#==#!=#!
&&#||
.TE
Of these, we need no special instrumentation for \fH&&\fR and \fH||\fR:
satisfying multi-condition coverage for the left- and right-hand sides
will necessarily yield both true and false values for the whole
expression.
.LP
Of course, a boolean return value might be one that was calculated
earlier.  Therefore, if the right-hand-side of an assignment statement
is one of the following types of expressions, the result must be both
zero and non-zero:
.TS
center box tab(#) ;
l l l l l l l .
<#<=#>#>=#==#!=#!
&&#||
.TE
.LP
Again, we need no special instrumentation for \fH&&\fR and \fH||\fR.
.LP
Suppose you have this code:
.nf

  flag = ! (b || c);
  return !flag;

.fi
\fBgreport -all\fR might show this:
.nf

"test.c", line 4: condition 1 (= expression) was taken TRUE 0, FALSE 3 times.
"test.c", line 4: condition 2 (b, 1) was taken TRUE 2, FALSE 1 times.
"test.c", line 4: condition 3 (c, 1) was taken TRUE 1, FALSE 0 times.
"test.c", line 5: condition 1 (return) was taken TRUE 3, FALSE 0 times.

.fi
.LP
Declarations are treated like assignment statements.  Given this (odd) code:
.nf

  float c1 = (c < d);

.fi
\fBgreport -all\fR might show this if multicondition and relational
operator coverage are turned on:
.nf

"multi.c", line 7: condition 1 (declaration) was taken TRUE 1, FALSE 1 times.
"multi.c", line 7: operator < might be >. (L!=R)  [1]
"multi.c", line 7: operator < might be <=. (L==R)  [1]
"multi.c", line 7: operator < is never barely true. (L==R-1)  [0]

.fi
.NH 2
Abbreviations in Multiple Condition Output
.LP
Operands in C may be arbitrarily complicated:
.nf

	Array[x->y.z].m->next

.fi
so GCT abbreviates to save space on the line.
.IP "Array references"
Array references are printed as \fIarrayname\fR[...]:
.nf

"example1.c", line 9: condition 1 (A[...], 1) was taken TRUE 2, FALSE 1 times.

.fi
If the arrayname is itself more complex than a single identifier, it
is printed as <...>.  Thus, the array reference (p->array)[5] might
yield this message:
.nf

"example1.c", line 9: condition 1 (<...>[...], 1) was taken TRUE 2, FALSE 1 times.

.fi
.IP Dereference
If the pointer being dereferenced is an identifier, the message will be 
.nf

"example1.c", line 9: condition 1 (*p, 1) was taken TRUE 2, FALSE 1 times.

.fi
Otherwise, it will be 
.nf

"example1.c", line 9: condition 1 (*<...>, 1) was taken TRUE 2, FALSE 1 times.

.fi
if, say, the C code were "*(p+1)".

.IP "Structures and unions"
If the structure is an identifier, its name is used; otherwise, the
usual <...> notation is used.  The field is always explicitly printed.
Examples:
.nf

	A.field is printed as "A.field".
	B->field is printed as "B->field".
	A[4]->field is printed as "<...>->field".

.fi
