summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStan Shebs <stanshebs@google.com>2018-01-24 12:42:41 -0800
committerStan Shebs <stanshebs@google.com>2018-01-24 16:03:40 -0800
commit4d954e99e984301fab6890ef9022af0016db39f5 (patch)
tree32a017fd28c356a176ac3b33835595f051637d17
parent85ad9efa68af4e841c659234b7c47f4f3816515b (diff)
downloadglibc-4d954e99e984301fab6890ef9022af0016db39f5.tar.gz
Add clang and debug support to conformance scripts
-rw-r--r--conform/GlibcConform.pm23
-rw-r--r--conform/Makefile3
-rw-r--r--conform/conformtest.pl10
-rw-r--r--conform/linknamespace.pl51
-rw-r--r--conform/list-header-symbols.pl4
5 files changed, 82 insertions, 9 deletions
diff --git a/conform/GlibcConform.pm b/conform/GlibcConform.pm
index ba9c7e822f..4e54685819 100644
--- a/conform/GlibcConform.pm
+++ b/conform/GlibcConform.pm
@@ -39,20 +39,26 @@ $CFLAGS{"POSIX2008"} = "-std=c99 -D_POSIX_C_SOURCE=200809L";
# Return a list of functions exported by a header, empty if an include
# of the header does not compile.
sub list_exported_functions {
- my ($cc, $standard, $header, $tmpdir) = @_;
+ my ($cc, $standard, $header, $tmpdir, $withclang) = @_;
my ($cc_all) = "$cc -D_ISOMAC $CFLAGS{$standard}";
my ($tmpfile) = "$tmpdir/list-$$.c";
my ($auxfile) = "$tmpdir/list-$$.c.aux";
+ my ($astfile) = "$tmpdir/list-$$.c.ast";
my ($ret);
my (%res) = ();
open (TMPFILE, ">$tmpfile") || die ("open $tmpfile: $!\n");
print TMPFILE "#include <$header>\n";
close (TMPFILE) || die ("close $tmpfile: $!\n");
+ if ($withclang ne "yes") {
$ret = system "$cc_all -c $tmpfile -o /dev/null -aux-info $auxfile > /dev/null";
+ } else {
+ $ret = system "$cc_all -c $tmpfile -o /dev/null -Xclang -ast-dump |grep FunctionDecl > $astfile";
+ }
unlink ($tmpfile) || die ("unlink $tmpfile: $!\n");
if ($ret != 0) {
return;
}
+ if ($withclang ne "yes") {
open (AUXFILE, "<$auxfile") || die ("open $auxfile: $!\n");
while (<AUXFILE>) {
s|/\*.*?\*/||g;
@@ -70,5 +76,20 @@ sub list_exported_functions {
}
close (AUXFILE) || die ("close $auxfile: $!\n");
unlink ($auxfile) || die ("unlink $auxfile: $!\n");
+ } else {
+ open (ASTFILE, "<$astfile") || die ("open $astfile: $!\n");
+ while (<ASTFILE>) {
+ s/^.*:[0-9][0-9]*:[0-9][0-9]* //g;
+ s/^.*:[0-9][0-9]* implicit //g;
+ s/^.*:[0-9][0-9]* //g;
+ if (/(\w+)\s* /) {
+ $res{$1} = 1;
+ } else {
+ die ("couldn't parse -ast-dump output: $_\n");
+ }
+ }
+ close (ASTFILE) || die ("close $astfile: $!\n");
+ unlink ($astfile) || die ("unlink $astfile: $!\n");
+ }
return sort keys %res;
}
diff --git a/conform/Makefile b/conform/Makefile
index 864fdeca21..6a72025f4b 100644
--- a/conform/Makefile
+++ b/conform/Makefile
@@ -178,6 +178,7 @@ $(conformtest-header-tests): $(objpfx)%/conform.out: \
$(PERL) -I. conformtest.pl --tmpdir=$(@D)/scratch --cc='$(CC)' \
--flags='$(conformtest-cc-flags)' --standard=$$std \
--headers=$$hdr $(conformtest-xfail) $(conformtest-cross) \
+ --withclang='$(with-clang)' \
> $@); \
$(evaluate-test)
@@ -185,6 +186,7 @@ $(linknamespace-symlists-tests): $(objpfx)symlist-%: list-header-symbols.pl
$(PERL) -I. -w $< --tmpdir=$(objpfx) --cc='$(CC)' \
--flags='$(conformtest-cc-flags)' --standard=$* \
--headers="$(strip $(conformtest-headers-$*))" \
+ --withclang='$(with-clang)' \
> $@ 2> $@.err; \
$(evaluate-test)
@@ -225,6 +227,7 @@ $(linknamespace-header-tests): $(objpfx)%/linknamespace.out: \
--stdsyms=$(objpfx)symlist-$$std --header=$$hdr \
--libsyms=$(objpfx)symlist-stdlibs-$$std \
--readelf='$(READELF)' \
+ --withclang='$(with-clang)' \
> $@ 2>&1); \
$(evaluate-test)
diff --git a/conform/conformtest.pl b/conform/conformtest.pl
index cb500f0e76..e12e072278 100644
--- a/conform/conformtest.pl
+++ b/conform/conformtest.pl
@@ -11,7 +11,7 @@ $cross = "";
$xfail_str = "";
GetOptions ('headers=s' => \@headers, 'standard=s' => \$standard,
'flags=s' => \$flags, 'cc=s' => \$CC, 'tmpdir=s' => \$tmpdir,
- 'cross' => \$cross, 'xfail=s' => \$xfail_str);
+ 'cross' => \$cross, 'xfail=s' => \$xfail_str, 'withclang=s' => \$withclang);
@headers = split(/,/,join(',',@headers));
# List of the headers we are testing.
@@ -270,9 +270,17 @@ sub checknamespace {
close (TESTFILE);
undef %errors;
+ if ($withclang eq "yes") {
+ open (CONTENT, "$CC $CFLAGS_namespace -E $fnamebase.c -P -Wp,-dM | sed -e '/^# [1-9]/d' -e '/^[[:space:]]*\$/d' |");
+ } else {
open (CONTENT, "$CC $CFLAGS_namespace -E $fnamebase.c -P -Wp,-dN | sed -e '/^# [1-9]/d' -e '/^[[:space:]]*\$/d' |");
+ }
loop: while (<CONTENT>) {
chop;
+ if ($withclang eq "yes") {
+ # Filter extra output coming from -dM
+ s/^(#[^ ]+ [^ (]+).*$/$1/g;
+ }
if (/^#define (.*)/) {
newtoken ($1, @allow);
} elsif (/^#undef (.*)/) {
diff --git a/conform/linknamespace.pl b/conform/linknamespace.pl
index 3fc6aca621..0445b32ae8 100644
--- a/conform/linknamespace.pl
+++ b/conform/linknamespace.pl
@@ -27,7 +27,9 @@ use Getopt::Long;
GetOptions ('header=s' => \$header, 'standard=s' => \$standard,
'flags=s' => \$flags, 'cc=s' => \$CC, 'tmpdir=s' => \$tmpdir,
'stdsyms=s' => \$stdsyms_file, 'libsyms=s' => \$libsyms_file,
- 'readelf=s' => \$READELF);
+ 'readelf=s' => \$READELF, 'withclang=s' => \$withclang);
+
+$debug = 1;
# Load the list of symbols that are OK.
%stdsyms = ();
@@ -162,7 +164,7 @@ foreach my $sym (@sym_data) {
# detected by this script if the same namespace issue applies for
# static linking.
-@c_syms = list_exported_functions ("$CC $flags", $standard, $header, $tmpdir);
+@c_syms = list_exported_functions ("$CC $flags", $standard, $header, $tmpdir, $withclang);
$cincfile = "$tmpdir/undef-$$.c";
$cincfile_o = "$tmpdir/undef-$$.o";
$cincfile_sym = "$tmpdir/undef-$$.sym";
@@ -177,9 +179,11 @@ system ("$CC $flags -D_ISOMAC $CFLAGS{$standard} -c $cincfile -o $cincfile_o")
system ("LC_ALL=C $READELF -W -s $cincfile_o > $cincfile_sym")
&& die ("readelf failed\n");
@elf_syms = list_syms ($cincfile_sym);
-unlink ($cincfile) || die ("unlink $cincfile: $!\n");
-unlink ($cincfile_o) || die ("unlink $cincfile_o: $!\n");
-unlink ($cincfile_sym) || die ("unlink $cincfile_sym: $!\n");
+if (!$debug) {
+ unlink ($cincfile) || die ("unlink $cincfile: $!\n");
+ unlink ($cincfile_o) || die ("unlink $cincfile_o: $!\n");
+ unlink ($cincfile_sym) || die ("unlink $cincfile_sym: $!\n");
+}
%seen_where = ();
%files_seen = ();
@@ -207,7 +211,31 @@ while (%current_undef) {
$seen_where{$ssym} = "$current_undef{$sym} -> [$file] $ssym";
}
}
+ # A clang build can leave strong undefined symbols in the file,
+ # instead of GC'ing them; filter them out.
foreach my $usym (@{$strong_undef_syms{$file}}) {
+ $alsoseen = 0;
+ foreach my $ssym (@{$seen_syms{$file}}) {
+ if ($ssym eq $usym) {
+ if ($debug) {
+ print "$usym is strong undef also seen in $file, skipping\n";
+ }
+ $alsoseen = 1;
+ last;
+ }
+ }
+ if ($alsoseen) {
+ next;
+ }
+ if ($debug) {
+ foreach my $file2 (@{$sym_objs{$sym}}) {
+ foreach my $ssym (@{$seen_syms{$file2}}) {
+ if ($ssym eq $usym) {
+ print " seen in $file2";
+ }
+ }
+ }
+ }
if (!defined ($all_undef{$usym})) {
$all_undef{$usym} = "$current_undef{$sym} -> [$file] $usym";
$new_undef{$usym} = "$current_undef{$sym} -> [$file] $usym";
@@ -220,14 +248,27 @@ while (%current_undef) {
$ret = 0;
foreach my $sym (sort keys %seen_where) {
+ if ($debug) {
+ print "RAW $seen_where{$sym}\n";
+ }
if ($sym =~ /^_/) {
next;
}
if (defined ($stdsyms{$sym})) {
+ if ($debug) {
+ print "$sym IS IN stdsyms\n";
+ }
next;
}
+ if ($debug) {
+ print "FINAL ";
+ }
print "$seen_where{$sym}\n";
$ret = 1;
}
+if ($debug) {
+ print "Return result is $ret\n";
+}
+
exit $ret;
diff --git a/conform/list-header-symbols.pl b/conform/list-header-symbols.pl
index 0db61bfe86..adb282c957 100644
--- a/conform/list-header-symbols.pl
+++ b/conform/list-header-symbols.pl
@@ -24,7 +24,7 @@ use GlibcConform;
use Getopt::Long;
GetOptions ('headers=s' => \$headers, 'standard=s' => \$standard,
- 'flags=s' => \$flags, 'cc=s' => \$CC, 'tmpdir=s' => \$tmpdir);
+ 'flags=s' => \$flags, 'cc=s' => \$CC, 'tmpdir=s' => \$tmpdir, 'withclang=s' => \$withclang);
@headers = split (/\s+/, $headers);
# Extra symbols possibly not found through -aux-info but still
@@ -67,7 +67,7 @@ $extra_syms{"POSIX2008"} = ["errno", "setjmp", "va_end", "environ",
%user_syms = ();
foreach my $header (@headers) {
- @syms = list_exported_functions ("$CC $flags", $standard, $header, $tmpdir);
+ @syms = list_exported_functions ("$CC $flags", $standard, $header, $tmpdir, $withclang);
foreach my $sym (@syms) {
if ($sym !~ /^_/) {
$user_syms{$sym} = 1;