@@ -156,10 +156,6 @@ sub parse
156
156
if (defined ($version ) && $version ne " " );
157
157
158
158
my $lineData = $fileInfo -> test($testname );
159
- # use branch data to derive MC/DC expression - so need
160
- # it, even if user didn't ask
161
- my $branchData = $fileInfo -> testbr($testname )
162
- if $lcovutil::br_coverage || $lcovutil::mcdc_coverage ;
163
159
my $mcdcData = $fileInfo -> testcase_mcdc($testname )
164
160
if $lcovutil::mcdc_coverage ;
165
161
@@ -170,129 +166,239 @@ sub parse
170
166
my $mcdc = $f -> {mcdc_records }
171
167
if $lcovutil::mcdc_coverage && exists ($f -> {mcdc_records });
172
168
173
- foreach my $s (@$segments ) {
174
- die (" unexpected segment data" ) unless scalar (@$s ) == 6;
175
- my ($line , $col , $count , $hasCount , $isRegion , $isGap ) =
176
- @$s ;
177
- next unless $hasCount ;
178
- $lineData -> append($line , $count );
169
+ my $index = 0;
170
+ my $currentLine = 0;
171
+
172
+ while ($index < $# $segments ) {
173
+ my $segment = $segments -> [$index ];
174
+ die (" unexpected segment data" )
175
+ unless scalar (@$segment ) == 6;
176
+ my ($line , $col , $count , $hasCount , $isRegionEntry , $isGap )
177
+ = @$segment ;
178
+ $currentLine = $line if !$currentLine ;
179
+ if ($hasCount ) {
180
+ $segment = $segments -> [$index + 1];
181
+ die (" unexpected segment data" )
182
+ unless scalar (@$segment ) == 6;
183
+ my ($next_line , $next_col , $next_count , $next_hasCount ,
184
+ $next_isRegionEntry , $next_isGap )
185
+ = @$segment ;
186
+ if ($currentLine == $next_line && !$next_isRegionEntry )
187
+ {
188
+ while ($next_line == $currentLine &&
189
+ ++$index < $# $segments ) {
190
+ $segment = $segments -> [$index + 1];
191
+ die (" unexpected segment data" )
192
+ unless scalar (@$segment ) == 6;
193
+ $next_line = $segment -> [0];
194
+ $count = $next_count
195
+ if ($count &&
196
+ $next_count > $count &&
197
+ $currentLine == $next_line );
198
+ $next_count = $segment -> [2];
199
+ }
200
+ $lineData -> append($currentLine , $count );
201
+ ++$currentLine ;
202
+ } else {
203
+ my $bound = $next_line ;
204
+ my $i = $index ;
205
+ while (!$next_isRegionEntry &&
206
+ $next_line == $bound &&
207
+ ++$i < $# $segments ) {
208
+ $segment = $segments -> [$i + 1];
209
+ die (" unexpected segment data" )
210
+ unless scalar (@$segment ) == 6;
211
+ $next_line = $segment -> [0];
212
+ $next_isRegionEntry = $segment -> [4];
213
+ }
214
+ --$bound
215
+ if ($next_isRegionEntry &&
216
+ $next_line == $bound &&
217
+ !($isRegionEntry && $line == $next_line ));
218
+ $count = $next_count
219
+ if $next_count > $count && $line == $next_line ;
220
+ while ($currentLine <= $bound ) {
221
+ $lineData -> append($currentLine , $count );
222
+ ++$currentLine ;
223
+ }
224
+ ++$index ;
225
+ }
226
+ } else {
227
+ do {
228
+ ++$index ;
229
+ $segment = $segments -> [$index ];
230
+ die (" unexpected segment data" )
231
+ unless scalar (@$segment ) == 6;
232
+ ($line , $col , $count , $hasCount ,
233
+ $isRegionEntry , $isGap ) = @$segment ;
234
+ } while (!$hasCount && $index < $# $segments );
235
+ $currentLine = $isRegionEntry ? $line : $line + 1;
236
+ }
179
237
}
180
-
181
- if ($branchData ) {
182
- my $currentLine = -1;
183
- my $branchIdx ;
238
+ if ($mcdc ) {
239
+ my @mcdcBranches ; # array (start line, start column, expression)
184
240
foreach my $branch (@$branches ) {
185
241
die (" unexpected branch data" )
186
242
unless scalar (@$branch ) == 9;
243
+ # Consider only branches of "MCDCBranchRegion" kind.
244
+ next if ($branch -> [-1] != 6);
187
245
my ($line , $startCol , $endline ,
188
246
$endcol , $trueCount , $falseCount ,
189
247
$fileId , $expandedId , $kind ) = @$branch ;
190
- if ($line != $currentLine &&
191
- defined ($lineData -> value($line ))) {
192
- $branchIdx = 0; # restart counter
193
- $currentLine = $line ;
194
- } else {
195
- # this branch is part of the current group
196
- ++$branchIdx ;
197
- }
198
248
my $expr =
199
249
$srcReader -> getExpr($line , $startCol , $endline ,
200
250
$endcol )
201
251
if $srcReader -> notEmpty();
202
-
203
- my $br =
204
- BranchBlock-> new($branchIdx , $trueCount , $expr );
205
- $branchData -> append($line , 0, $br , $filename );
252
+ push (@mcdcBranches , [$line , $startCol , $expr ]);
206
253
}
207
- }
208
- if ($mcdc ) {
209
254
foreach my $m (@$mcdc ) {
210
- # what are fileID and kind?
211
255
die (" unexpected MC/DC data" ) unless scalar (@$m ) == 7;
212
- my ($line , $startCol , $endLine , $endcol , $fileId ,
256
+ my ($line , $startCol , $endLine , $endCol , $expandedId ,
213
257
$kind , $cov )
214
258
= @$m ;
215
259
die (" unexpected MC/DC cov" )
216
260
unless ' ARRAY' eq ref ($cov );
217
- my $groupSize = scalar (@$cov );
218
261
219
262
# read the source line and extract the expression...
220
263
my $expr =
221
264
$srcReader -> getExpr($line , $startCol , $endLine ,
222
- $endcol )
265
+ $endCol )
223
266
if ($srcReader -> notEmpty());
224
-
267
+ my @brExprs ;
268
+ foreach my $branch (@mcdcBranches ) {
269
+ my ($brLine , $brCol , $brExpr ) = @$branch ;
270
+ if (($brLine > $line ||
271
+ ($brLine == $line && $brCol >= $startCol ))
272
+ &&
273
+ ($brLine < $endLine ||
274
+ ($brLine == $endLine && $brCol <= $endCol ))
275
+ ) {
276
+ push (@brExprs , [$brLine , $brCol , $brExpr ]);
277
+ }
278
+ }
279
+ @brExprs =
280
+ sort { $a -> [0] <=> $b -> [0] || $a -> [1] <=> $b -> [1] }
281
+ @brExprs ;
225
282
my $current_mcdc =
226
283
$mcdcData -> new_mcdc($mcdcData , $line );
227
- my $branch = $branchData -> value( $line );
228
- my $idx = 0;
284
+ my $groupSize = scalar ( @$cov );
285
+ my $idx = 0;
229
286
foreach my $c (@$cov ) {
230
- my $branchExpr =
231
- $branch -> getBlock(0)-> [$idx ]-> expr()
232
- if $branch &&
233
- (scalar (@{$branch -> getBlock(0)}) > $idx );
234
- $branchExpr =
235
- defined ($branchExpr ) ?
236
- " '$branchExpr ' in '$expr '" :
287
+ my $branchExpr = $brExprs [$idx ]-> [2]
288
+ if $groupSize == scalar (@brExprs );
289
+ my $fullExpr =
290
+ defined ($branchExpr ) &&
291
+ defined ($expr ) ? " '$branchExpr ' in '$expr '" :
237
292
$idx ;
238
-
239
293
$current_mcdc -> insertExpr($filename , $groupSize , 0,
240
- $c , $idx , $branchExpr );
294
+ $c , $idx , $fullExpr );
241
295
$current_mcdc -> insertExpr($filename , $groupSize , 1,
242
- $c , $idx , $branchExpr );
296
+ $c , $idx , $fullExpr );
243
297
++$idx ;
244
298
}
245
299
$mcdcData -> close_mcdcBlock($current_mcdc );
246
300
}
247
- } # MCDC
248
- $fileInfo -> testbr()-> remove($testname )
249
- if $lcovutil::mcdc_coverage && !$lcovutil::br_coverage ;
301
+ }
250
302
lcovutil::info(2, " finished parsing $filename \n " );
251
303
}
252
304
253
- next unless $lcovutil::func_coverage ;
254
305
foreach my $f (@{$k -> {functions }}) {
255
306
my $name = $f -> {name };
256
307
my $filenames = $f -> {filenames }; # array
257
- if ($# $filenames != 0) {
258
- lcovutil::ignorable_error($lcovutil::ERROR_USAGE ,
259
- " unsupported: function $name associated with multiple files"
260
- );
261
- next ;
262
- }
263
308
my $filename =
264
309
ReadCurrentSource::resolve_path($filenames -> [0], 1);
265
- if (TraceFile::skipCurrentFile($filename )) {
266
- if (!exists ($lcovutil::excluded_files {$filename })) {
267
- $lcovutil::excluded_files {$filename } = 1;
268
- lcovutil::info(" Excluding $filename \n " );
269
- }
270
- next ;
271
- }
310
+ next if (TraceFile::skipCurrentFile($filename ));
272
311
die (' unexpected unknown file \' ' . $filenames -> [0] . ' \' ' )
273
312
unless $top -> file_exists($filename );
274
- my $info = $top -> data($filename );
275
- my $count = $f -> {count };
276
- my $regions = $f -> {regions }; # startline/col, endline/col/
313
+ $srcReader -> open ($filename );
314
+
315
+ my $info = $top -> data($filename );
316
+ my $count = $f -> {count };
317
+ my $regions = $f -> {regions }; # startline/col, endline/col/
318
+ my $branches = $f -> {branches };
277
319
278
320
my $functionMap = $info -> testfnc($testname );
321
+ # use branch data to derive MC/DC expression - so need
322
+ # it, even if user didn't ask
323
+ my $branchData = $info -> testbr($testname )
324
+ if $lcovutil::br_coverage ;
279
325
my $startLine = $regions -> [0]-> [0]; # startline of first region
280
- # NOTE: might be a mistake to grab the end line of the last region -
281
- # LCOV follows GCC behaviour and associates lines with where they
282
- # start - not where they end...
283
- my $endline = $regions -> [-1]-> [2]; # endline of last region
284
- my $func =
285
- $functionMap -> define_function($name , $startLine , $endline )
286
- unless defined ($functionMap -> findName($name ));
287
- $functionMap -> add_count($name , $count );
288
-
289
- # for the moment - don't worry about the coverpoints in the function
290
- # my $branches = $f->{branches};
291
- # my $mcdc = $f->{mcdc_records} if exists($f->{mcdc_records});
292
- # foreach my $r (@$regions) {
293
- # my ($startLine, $startCol, $endLine, $endCol, $count, $fileId,
294
- # $expandedId, $kind) = @$r;
295
- # }
326
+ my $endline = $regions -> [0]-> [2]; # endline of last region
327
+ if ($lcovutil::func_coverage ) {
328
+ my $func =
329
+ $functionMap -> define_function($name , $startLine ,
330
+ $endline )
331
+ unless defined ($functionMap -> findName($name ));
332
+ $functionMap -> add_count($name , $count );
333
+ }
334
+ if ($branchData ) {
335
+ my $funcBranchData = BranchData-> new();
336
+ my $regionIdx = 0;
337
+ foreach my $b (@$branches ) {
338
+ die (" unexpected branch data" ) unless scalar (@$b ) == 9;
339
+ my ($brStartLine , $brStartCol , $endLine ,
340
+ $endCol , $trueCount , $falseCount ,
341
+ $fileId , $expandedId , $kind ) = @$b ;
342
+ my ($line , $col ) = ($brStartLine , $brStartCol );
343
+ my $expr ;
344
+
345
+ if ($fileId == 0) {
346
+ $expr =
347
+ $srcReader -> getExpr($line , $col , $endLine ,
348
+ $endCol )
349
+ if $srcReader -> notEmpty();
350
+ } else {
351
+ # Find a source range, which contains the branch.
352
+ while ($regionIdx < scalar (@$regions )) {
353
+ my ($rStartLine , $rStartCol , $rEndLine ,
354
+ $rEndCol , $rCount , $rFileId ,
355
+ $rExpandedId , $rKind
356
+ ) = @{$regions -> [$regionIdx ]};
357
+ if ($rExpandedId == $fileId && $rKind == 1) {
358
+ if ($rFileId != 0) {
359
+ # Check previous regions to find one
360
+ # that describes lines of the function's
361
+ # source file.
362
+ my $rIdx = $regionIdx - 1;
363
+ $fileId = $rFileId ;
364
+ while ($fileId != 0 && $rIdx >= 0) {
365
+ ($rStartLine , $rStartCol ,
366
+ $rEndLine , $rEndCol ,
367
+ $rCount , $rFileId ,
368
+ $rExpandedId , $rKind
369
+ ) = @{$regions -> [$rIdx ]};
370
+ $fileId = $rFileId
371
+ if ($rExpandedId == $fileId &&
372
+ $rKind == 1);
373
+ --$rIdx ;
374
+ }
375
+ }
376
+ ($line , $col ) = ($rStartLine , $rStartCol );
377
+ last ;
378
+ }
379
+ ++$regionIdx ;
380
+ }
381
+ }
382
+ # Processed branch on the same line doesn't have to be the previous.
383
+ my $brEntry = $funcBranchData -> value($line );
384
+ my $branchIdx =
385
+ !defined ($brEntry ) ? 0 :
386
+ scalar (@{$brEntry -> getBlock(0)});
387
+ my $br =
388
+ BranchBlock-> new($branchIdx , $trueCount ,
389
+ !defined ($expr ) ? $branchIdx :
390
+ " (" . $expr . " ) == True" );
391
+ $funcBranchData -> append($line , 0, $br , $filename );
392
+
393
+ ++$branchIdx ;
394
+ $br =
395
+ BranchBlock-> new($branchIdx , $falseCount ,
396
+ !defined ($expr ) ? $branchIdx :
397
+ " (" . $expr . " ) == False" );
398
+ $funcBranchData -> append($line , 0, $br , $filename );
399
+ }
400
+ $branchData -> union($funcBranchData );
401
+ }
296
402
}
297
403
}
298
404
lcovutil::info(2, " finished $jsonFile \n " );
@@ -324,7 +430,8 @@ my %opts = ('test-name|t=s' => \$testname,
324
430
' output-filename|o=s' => \$output_filename ,);
325
431
my %rc_opts ;
326
432
if (!lcovutil::parseOptions(\%rc_opts , \%opts , \$output_filename )) {
327
- print (STDERR " argparse failed" );
433
+ print (STDERR " argparse failed\n " );
434
+ exit (1);
328
435
}
329
436
330
437
my $info = parse($testname , @ARGV );
0 commit comments