When retrieving the lambda expressions inside a clang cursor, we were
traversing recursively all the nodes in the cursor subtree. In addition
to being very inefficient, this resulted in lambda expressions being
processed multiple times.
To fix this, we integrate the processing of lambda expression to the
processing of decisions, similarly to what is done to process declare
expressions in Ada.
The instrumentation scheme for C++ for ranges resulted in incorrect code
when initializer lists were involved, e.g.:
```
for (auto i : {1, 2) {
<for_body>
}
```
being instrumented as
```
for (auto i : (witness(), {1, 2}) {
<for_body>
}
```
which is invalid C++ code.
To fix this, we now instrument such expressions as followed:
```
witness();
for (auto i : {1, 2}) {
<for_body>
}
```
We can't execute the loop statement without executing the witness
with a goto as it is forbidden to bypass initialization statements in C++.
When there is an initialization statement, e.g.:
```
for (int j = 0; auto i : {1, 2}){}
```
we actually introduce an outer scope and instrument as followed:
```
{
witness_j();
int j = 0;
witness_i();
for (auto i : {1, 2}){}
}
```
(cherry picked from commit c29e1be8bf)
gnatcov used to crash when instrumenting source code that consisted
solely of non-instrumentable constructs. This was due to an implicit
assumption that every source of interest should be present in the
UIC.Instrumented_Entities map, which wasn't the case in this scenario.
Fix the code to ensure the assumption's validity.
Instrumenting constexpr functions violates the constexpr semantics and
there is no straightforward valid way of instrumenting such code
constructs.
Skip their instrumentation altogether for the moment, as their use is
quite limited (they are only allowed to return literal values).
If the parsing failed because of an error in the user code, we should
emit the diagnostics reported by clang to let the user know that
coverage analysis may be incomplete.
As we preprocess code with another compiler configuration than the clang
one, we may have compiler-specific code, notably in system-headers, so
we also need to filter out a lot of messages to avoid issuing spurious
warning messages. The heuristic picked is to only keep diagnostics whose
presumed location file is a file of interest (belonging to the project).
This could be revisited if there are still too many false positives (as
we will have false positives raised on compiler-specific user code).