mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-23 06:05:27 +00:00
728cacc8ab
CLang's optimizer is more aggressive at inlining functions than gcc and so will often inline functions that our tests want to mock-override. This causes the test to fail in bizarre ways. We don't want to disable inlining completely, but we must at least prevent inlining of mocked functions. Fortunately there is a 'noinline' attribute that lets us control this per function. A syntax check rule is added that parses tests/*mock.c to extract the list of functions that are mocked (restricted to names starting with 'vir' prefix). It then checks that src/*.h header file to ensure it has a 'ATTRIBUTE_NOINLINE' annotation. This should prevent use from bit-rotting in future. Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
73 lines
1.5 KiB
Perl
73 lines
1.5 KiB
Perl
#!/usr/bin/perl
|
|
|
|
my %noninlined;
|
|
my %mocked;
|
|
|
|
# Functions in public header don't get the noinline annotation
|
|
# so whitelist them here
|
|
$noninlined{"virEventAddTimeout"} = 1;
|
|
|
|
foreach my $arg (@ARGV) {
|
|
if ($arg =~ /\.h$/) {
|
|
#print "Scan header $arg\n";
|
|
&scan_annotations($arg);
|
|
} elsif ($arg =~ /mock\.c$/) {
|
|
#print "Scan mock $arg\n";
|
|
&scan_overrides($arg);
|
|
}
|
|
}
|
|
|
|
my $warned = 0;
|
|
foreach my $func (keys %mocked) {
|
|
next if exists $noninlined{$func};
|
|
|
|
$warned++;
|
|
print STDERR "$func is mocked at $mocked{$func} but missing noinline annotation\n";
|
|
}
|
|
|
|
exit $warned ? 1 : 0;
|
|
|
|
|
|
sub scan_annotations {
|
|
my $file = shift;
|
|
|
|
open FH, $file or die "cannot read $file: $!";
|
|
|
|
my $func;
|
|
while (<FH>) {
|
|
if (/^\s*(\w+)\(/ || /^(?:\w+\*?\s+)+(?:\*\s*)?(\w+)\(/) {
|
|
my $name = $1;
|
|
if ($name !~ /ATTRIBUTE/) {
|
|
$func = $name;
|
|
}
|
|
} elsif (/^\s*$/) {
|
|
$func = undef;
|
|
}
|
|
if (/ATTRIBUTE_NOINLINE/) {
|
|
if (defined $func) {
|
|
$noninlined{$func} = 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
close FH
|
|
}
|
|
|
|
sub scan_overrides {
|
|
my $file = shift;
|
|
|
|
open FH, $file or die "cannot read $file: $!";
|
|
|
|
my $func;
|
|
while (<FH>) {
|
|
if (/^(\w+)\(/ || /^\w+\s*(?:\*\s*)?(\w+)\(/) {
|
|
my $name = $1;
|
|
if ($name =~ /^vir/) {
|
|
$mocked{$name} = "$file:$.";
|
|
}
|
|
}
|
|
}
|
|
|
|
close FH
|
|
}
|