How to handle Coveragescanner error messages and warnings

What does the warning "Instrumentation is different" mean?

Sometimes during compilation of a C/C++ program, Coco issues a warning of the form

Warning (Squish Coco): Compilation of 'myproject/header.h': Instrumentation of source file 'myproject/header.h' is different

followed by several more lines. What does this mean?

Explanation

In C and C++, the content of a source file does not completely determine to what code it compiles. This is because preprocessor symbols can be set at compile time and determine – usually via #ifdef statements – which source code gets actually translated.

This means that it is possible that a source file is compiled several times with different preprocessor settings. This may lead to different compiled code and, if Coco is involved, to different instrumentations of the same file. If Coco notices this, it issues the "Instrumentation is different" message.

The message is however only a warning. Coco treats the different versions of the file as different files and when they are displayed in CoverageBrowser or in a report, the versions are distinguished by numbers at the end. A file header.h could be displayed as header.h#1 and header.h#2 if there are two versions of it.

An example

What exactly is going on and how the error message must be understoond is best seen from an example. The first ingredient must be source a file that is can be compiled to different code depending on an external setting. The following file, header.h, is such a source. It defines a function, letter(), the compilation of which depends on whether the preprocessor symbol A is defined or not:

#ifndef HEADER_H
#define HEADER_H

static inline char letter()
{
#ifdef A
    return 'a';
#else
    return 'b';
#endif
}

#endif

Then there are two files that use this library. One is a.cpp,

#include "a.h"
#include "header.h"
#include <iostream>

void a()
{
    std::cout << "Letter A: " << letter() << "\n";
}

the other one, b.cpp. (The header files, a.h and b.h, are here omitted.)

#include "b.h"
#include "header.h"
#include <iostream>

void b()
{
    std::cout << "Letter B: " << letter() << "\n";
}

Note that the two file are essentially the same and by themselves do not contain any code that is influenced by the symbol A. Both however include header.h. And that means that the preprocessed versions of a.cpp and b.cpp – the versions that CoverageScanner sees and instruments – contain a preprocessed version of header.h and that they depend on the symbol A.

Finally there is program, main.cpp, that uses them both.

#include "a.h"
#include "b.h"

int main()
{
    a();
    b();
    return 0;
}

All these files must be compiled, but a.cpp and b.cpp must be compiled with different flags: The symbol A should be defined for a.cpp but not for b.cpp. If this project is compiled with a makefile, it could look like this;

main: main.cpp a.o b.o
    g++ -o main main.cpp a.o b.o

a.o: a.cpp a.h header.h
    g++ -DA -c -o a.o a.cpp

b.o: b.cpp b.h header.h
    g++     -c -o b.o b.cpp

One can see here the additional flag -DA in the compilation of a.cpp; it defines the symbol A. With other build systems, the settings will be similar.

When such a project is compiled with instrumentation enabled, the warning from above appears. Its full text is:

Warning (Squish Coco): Compilation of 'myproject/header.h': Instrumentation of source file 'myproject/header.h' is different
Warning (Squish Coco):   Source line 7 of file 'myproject/header.h' is differently instrumented in the database 'main.csmes' and 'b.o.csmes'
Warning (Squish Coco): Original:
Warning (Squish Coco):     4: inline char letter()
Warning (Squish Coco):     5: {
Warning (Squish Coco):     6: #ifdef A
Warning (Squish Coco): >>> 7:     return 'a';
Warning (Squish Coco):     8: #else
Warning (Squish Coco):     9:     return 'b';
Warning (Squish Coco):     10: #endif
Warning (Squish Coco): [ALL] Inconsistent instrumentations in: myproject/header.h
Warning (Squish Coco):
Warning (Squish Coco): [1/2] Source files:                     myproject/a.cpp
Warning (Squish Coco): [1/2] Distinct define flags:            -DA
Warning (Squish Coco):
Warning (Squish Coco): [2/2] Source files:                     myproject/b.cpp
Warning (Squish Coco):
Warning (Squish Coco): [ALL] Common instrumentation options:   --cs-combine-switch-cases
Warning (Squish Coco):                                         --cs-count
Warning (Squish Coco):                                         --cs-function-coverage
Warning (Squish Coco):                                         --cs-line-coverage
Warning (Squish Coco):                                         --cs-mcc

One sees here:

  • The first line shows that the error occurred during the compilation of the file header.h.
  • The second line shows that the problem was found when the information from the file b.o.csmes was merged into main.csmes, and that it occurred on line 7.

    What actually happened was that at first, main.csmes did not contain any information about header.h. Then, during the link step, a.o.csmes got merged. It contained information about header.h in the version with the symbol A defined. And after that, b.o.csmes got merged too – with a different version of header.h. This then caused the inconsistency.

  • The next lines show the line that is instrumented differently: it is the line with return 'a'; and the first line that is only part of the code when A is defined.

    The three lines before and three lines after this line are also shown. The number of context lines can be set with the flag –cs-verbose-source-lines.

  • These differences could be caused by compiler options. The following lines, beginning with the first line that starts with [ALL], summarizes the options in a form that is easy to read.

    The summary consists of several sections, each prefixed by an expression in square braces. The prefix is either [ALL] or something like [1/2]. Lines that start with [ALL] refer to all files while others refer to a group of files that were compiled with the same command line options. The first number is the number of the file group and the second is the number of all file groups. This means that [1/2] refers to the first of two groups.

    All file group sections have the same form: First there is a line that lists the contents of the group. In our example, the first group (and also the second) consists of just one file:

    Warning (Squish Coco): [1/2] Source files:                     myproject/a.cpp

    The following line then lists the distinct define flags, that is those that do not appear in all groups. In the first group, this is -DA, as expected, since we have defined the symbol A only for the file a.cpp. The second group has no distinct flags.

    There are actually four kinds of command line options that can be listed for each group:

    • Distinct define flags: The flags that define compiler symbols.
    • Distinct include directories: This is for the flags the define the directories in which #include finds header files. (The directories are sorted alphabetically, so that the rare errors in which the compilation depends on the order of the include paths cannot be caught this way.)
    • Distinct instrumentation options: This is for coveragescanner options.
    • Distinct compiler flags (others): For the rest of the flags.

    After the file groups and their options, the command line options common to all the source files are listed with the prefix [ALL].

    In our example, only instrumentation options are listed.

Coco v7.2.0 ©2024 The Qt Company Ltd.
Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.