From ef606e39d759741a392fcf402d75b3a20f43a3db Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Wed, 6 Nov 2019 15:32:20 +0100 Subject: [PATCH 01/36] Add new group of C99 tests --- test/Makefile | 6 ++++++ test/small1/c99-bool.c | 20 ++++++++++++++++++ test/small1/c99-complex.c | 19 +++++++++++++++++ test/small1/c99-predefined.c | 11 ++++++++++ test/small1/c99-struct.c | 41 ++++++++++++++++++++++++++++++++++++ test/testcil.pl | 6 ++++++ 6 files changed, 103 insertions(+) create mode 100644 test/small1/c99-bool.c create mode 100644 test/small1/c99-complex.c create mode 100644 test/small1/c99-predefined.c create mode 100644 test/small1/c99-struct.c diff --git a/test/Makefile b/test/Makefile index 30407d780..b86e1d7f8 100644 --- a/test/Makefile +++ b/test/Makefile @@ -194,6 +194,12 @@ testrun/% : $(SMALL1)/%.c cd $(SMALL1); ./$*.exe echo SUCCESS +testrunc99/% : $(SMALL1)/%.c + cd $(SMALL1); $(CILLY) --nomerge --commPrintLn \ + $(CFLAGS) -std=c99 $(EXEOUT)$*.exe $*.c + cd $(SMALL1); ./$*.exe + echo SUCCESS + testrungcc/% : $(SMALL1)/%.c mustbegcc cd $(SMALL1); $(CILLY) --nomerge --commPrintLn \ $(CFLAGS) $(EXEOUT)$*.exe $*.c diff --git a/test/small1/c99-bool.c b/test/small1/c99-bool.c new file mode 100644 index 000000000..2f2074321 --- /dev/null +++ b/test/small1/c99-bool.c @@ -0,0 +1,20 @@ +#include +#include +#include "testharness.h" +int main(void) +{ + bool b = 17; + _Bool b1 = 17; + + if(b == 1) { + + } else { + E(1); + } + + if(b1 == 1) { + + } else { + E(2); + } +} diff --git a/test/small1/c99-complex.c b/test/small1/c99-complex.c new file mode 100644 index 000000000..cb90ae492 --- /dev/null +++ b/test/small1/c99-complex.c @@ -0,0 +1,19 @@ +#include +#include +#include + +int main(void) +{ + double complex z1 = I * I; // imaginary unit squared + printf("I * I = %.1f%+.1fi\n", creal(z1), cimag(z1)); + + double complex z2 = pow(I, 2); // imaginary unit squared + printf("pow(I, 2) = %.1f%+.1fi\n", creal(z2), cimag(z2)); + + double PI = acos(-1); + double complex z3 = exp(I * PI); // Euler's formula + printf("exp(I*PI) = %.1f%+.1fi\n", creal(z3), cimag(z3)); + + double complex z4 = 1+2*I, z5 = 1-2*I; // conjugates + printf("(1+2i)*(1-2i) = %.1f%+.1fi\n", creal(z4*z5), cimag(z4*z5)); +} diff --git a/test/small1/c99-predefined.c b/test/small1/c99-predefined.c new file mode 100644 index 000000000..13d2d6f15 --- /dev/null +++ b/test/small1/c99-predefined.c @@ -0,0 +1,11 @@ +#include +int main(void) +{ + printf("%s\n", __FILE__); + printf("%d\n", __LINE__); + printf("%s\n", __func__); + printf("%s\n", __DATE__); + printf("%s\n", __TIME__); + printf("%ld\n", __STDC_VERSION__); + return 0; +} diff --git a/test/small1/c99-struct.c b/test/small1/c99-struct.c new file mode 100644 index 000000000..43d15b189 --- /dev/null +++ b/test/small1/c99-struct.c @@ -0,0 +1,41 @@ +struct point { + int x, y; +}; + +struct fops { + int open, read, write, close; +}; + +struct fam { + int i; + int arr[]; +}; + +void foo( struct point p1, struct point p2) +{ + int a[6] = { [4] = 29, [2] = 15 }; + struct { int x,y; } ar[ 4] = { [1].x=23, [3].y=34, [1].y=-1, [1].x=12}; + struct fops f2 = { .open=0, .close=1, .read=2}; + + struct fam *s = malloc(sizeof(struct fam) + 17ul*sizeof(int)); + s->arr[5] = 12; +} + +void copy2( char* restrict s1, char* restrict s2, int n) +{ + while (n--) + *s1++ = *s2++; +} + +int main() { + struct point p1 = { 2, 4}; // this is standard + p1 = (struct point){ 1, 3}; // this is new + + // passing to the function + foo( (struct point){ 10, 11}, (struct point){ 1, 2}); + + // constructing an array + char **sx = (char *[]){ "Adam", "Eva", "Simon"}; + + return 0; +} diff --git a/test/testcil.pl b/test/testcil.pl index 353e20028..33f19ead1 100644 --- a/test/testcil.pl +++ b/test/testcil.pl @@ -720,6 +720,12 @@ sub addToGroup { addTest("test/shell-escape SHELL_ESCAPE=1"); +# c99 readiness tests +addTest("testrunc99/c99-bool"); +addTest("testrunc99/c99-predefined"); +addTest("testrunc99/c99-struct"); +addTest("testrunc99/c99-complex"); + # ---------------- c-torture ------------- ## if we have the c-torture tests add them ## But only if the ctorture group was specfied From 69bcd09b9276f3fdd036a5be314865e2e8afe750 Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Wed, 6 Nov 2019 15:40:05 +0100 Subject: [PATCH 02/36] Include stdlib.h in c99-struct example --- test/small1/c99-struct.c | 1 + 1 file changed, 1 insertion(+) diff --git a/test/small1/c99-struct.c b/test/small1/c99-struct.c index 43d15b189..8e23ede8d 100644 --- a/test/small1/c99-struct.c +++ b/test/small1/c99-struct.c @@ -1,3 +1,4 @@ +#include struct point { int x, y; }; From 1ddbbe0876654524d4cc483a6f42bdfa822c562c Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Wed, 6 Nov 2019 15:47:50 +0100 Subject: [PATCH 03/36] Add test for universal character names --- test/small1/c99-universal-character-names.c | 3 + test/testcil.pl | 101 ++++++++++---------- 2 files changed, 54 insertions(+), 50 deletions(-) create mode 100644 test/small1/c99-universal-character-names.c diff --git a/test/small1/c99-universal-character-names.c b/test/small1/c99-universal-character-names.c new file mode 100644 index 000000000..d9a502644 --- /dev/null +++ b/test/small1/c99-universal-character-names.c @@ -0,0 +1,3 @@ +int main() { + int \u03B1 = 5; +} diff --git a/test/testcil.pl b/test/testcil.pl index 33f19ead1..781a64772 100644 --- a/test/testcil.pl +++ b/test/testcil.pl @@ -61,10 +61,10 @@ # 1001 - Parsing # 1002 - cabs2cil # 1003 - Compilation -# 1004 - Running +# 1004 - Running -my %commonerrors = +my %commonerrors = ("^Parsing " => sub { $_[1]->{instage} = 1001; }, "^Converting CABS" => sub { $_[1]->{instage} = 1002; }, @@ -73,27 +73,27 @@ # We are seeing an error from make. Try to classify it based on the stage # in which we are - "^make: \\*\\*\\*" => - sub { + "^make: \\*\\*\\*" => + sub { if($_[1]->{ErrorCode} == 0) { $_[1]->{ErrorCode} = $_[1]->{instage}; }}, - + #"[sS]yntax error" => sub { $_[1]->{ErrorCode} = 1000; }, - + # Collect some more parameters # Now error messages - "^((Error|Bug|Unimplemented): .+)\$" + "^((Error|Bug|Unimplemented): .+)\$" => sub { if(! defined $_[1]->{ErrorMsg}) { $_[1]->{ErrorMsg} = $_[2];} }, "^(.+ : error .+)\$" => sub { if(! defined $_[1]->{ErrorMsg}) { $_[1]->{ErrorMsg} = $_[2];} }, - "^(.+:\\d+: (Error|Unimplemented|Bug):.+)\$" + "^(.+:\\d+: (Error|Unimplemented|Bug):.+)\$" => sub { if(! defined $_[1]->{ErrorMsg}) { $_[1]->{ErrorMsg} = $_[2];} }, "^(.+: fatal error.+)\$" => sub { if(! defined $_[1]->{ErrorMsg}) { $_[1]->{ErrorMsg} = $_[2];} }, - "^stackdump: Dumping stack trace" => + "^stackdump: Dumping stack trace" => sub { if(! defined $_[1]->{ErrorMsg}) { $_[1]->{ErrorMsg} = $_[2];} }, @@ -104,7 +104,7 @@ "^TOTAL\\s+([\\d.]+) s" => sub { $_[1]->{CURE} = $_[2]; }, ); - + # Add a test. # command is the base name of the tests + space separated arguments # extrargs are passed on the command line for each test @@ -113,7 +113,7 @@ sub addTest { my($command, %extrafields) = @_; my $self = $main::globalTEST; - my ($name, $extraargs) = + my ($name, $extraargs) = ($command =~ /^(\S+) ?(.*)$/); # name is first word my $theargs = $self->testCommandExtras($extraargs); @@ -178,7 +178,7 @@ sub addToGroup { Dir => "..", Cmd => "$make doc", Group => ["doc"]); - + # Now add tests addTest("testrun/const-array-init WARNINGS_ARE_ERRORS=1"); addTest("testrun/const-struct-init WARNINGS_ARE_ERRORS=1"); @@ -210,7 +210,7 @@ sub addToGroup { addTest("testrun/question2"); addTest("testrun/question3 USE_LOGICAL_OPERATORS=1"); addTest("test/argcast"); -addBadComment("test/argcast", +addBadComment("test/argcast", "Notbug. CIL bases type for implicit functions based on first call's argument."); addTest("test/array1"); addTest("test/array2"); @@ -244,7 +244,7 @@ sub addToGroup { addTest("test/packed2 _GNUCC=1"); addTest("test/bitfield"); addTest("testrun/bitfield3"); - + addTest("testrun/bitfield2"); addTest("testrun/call2 "); addTest("test/cast1"); @@ -275,14 +275,14 @@ sub addToGroup { addTest("testrun/enum2"); addTest("test/func"); addTest("test/funcarg "); -addBadComment("test/funcarg", +addBadComment("test/funcarg", "Bug. In parser (argument of function type)"); addTest("testrun/func2"); addTest("testrun/func3"); addTest("testrun/func4"); addTest("test/func10 "); -addBadComment("test/func10", +addBadComment("test/func10", "Bug. Cannot parse some strange K&R function definition"); addTest("test/globals"); addTest("test/globals2 "); @@ -325,7 +325,7 @@ sub addToGroup { addTest("testrun/inline2 _GNUCC=1"); addTest("test/inline3 _GNUCC=1"); addTest("test/decl2 _GNUCC=1"); -addBadComment("test/decl2", +addBadComment("test/decl2", "Bug. An old-style argument type should go through the default type conversion before being added to the function's type."); addTest("test/jmp_buf"); addTest("test/linux_atomic _GNUCC=1"); @@ -340,7 +340,7 @@ sub addToGroup { addTest("testrun/perror1"); addTest("test/pure"); addTest("testrun/post-assign "); -addBadComment("testrun/post-assign", +addBadComment("testrun/post-assign", "Minor. CIL does not have the same evaluation order for ++ as gcc"); addTest("test/printf "); addTest("test/printf_const "); @@ -391,7 +391,7 @@ sub addToGroup { addTest("testrun/memcpy1"); addTest("test/noreturn "); - + addTest("test/constrexpr "); addTest("testrun/flexible-array-member "); @@ -417,8 +417,8 @@ sub addToGroup { addTest("testrun/wchar3"); addTest("testrun/wchar4"); addTest("testrun/wchar5 "); -addTest("testrun/wchar6"); -addTest("testrun/wchar7"); +addTest("testrun/wchar6"); +addTest("testrun/wchar7"); addTest("testrun/escapes"); addTest("test-bad1/wchar-bad "); addTest("testrun/addrof3 _GNUCC=1"); @@ -470,7 +470,7 @@ sub addToGroup { addTest("arcombine _GNUCC=1"); addTest("testrun/funptr1"); addTest("testrun/typespec1 _GNUCC=1"); -addBadComment("testrun/typespec1", +addBadComment("testrun/typespec1", "Notbug. GCC 4 no longer allows this, so the error is fine."); addTest("testrun/returnvoid "); addTest("testrun/returnvoid1 "); @@ -479,17 +479,17 @@ sub addToGroup { addTest("testrun/void _GNUCC=1"); addTest("test/voidtypedef "); addTest("testrun/wrongnumargs "); -addBadComment("testrun/wrongnumargs", +addBadComment("testrun/wrongnumargs", "Notbug. Should fail since we don't pad argument lists"); addTest("test/restrict EXTRAARGS=-std=c9x _GNUCC=1"); addTest("test/restrict1 _GNUCC=1"); addTest("testrun/rmtmps1 "); addTest("testrun/rmtmps2 _GNUCC=1"); addTest("test/proto1 "); -addBadComment("test/proto1", +addBadComment("test/proto1", "Bug. CIL doesn't like pointers to old-style functions..."); addTest("test/proto2 "); -addBadComment("test/proto2", +addBadComment("test/proto2", "Bug. In parser (precedences)"); addTest("testrun/struct1 "); addTest("testrun/voidarg "); @@ -502,13 +502,13 @@ sub addToGroup { addTest("runall/extinline "); addTest("testrun/rmtmps-attr "); -addBadComment("testrun/rmtmps-attr", +addBadComment("testrun/rmtmps-attr", "Bug. A limitation of our support for attributes"); - + addTest("testrun/vsp"); addTest("test/cpp-2 "); -addBadComment("test/cpp-2", +addBadComment("test/cpp-2", "Bug. In parser (empty pragmas)"); addTest("test/cpp-3 _GNUCC=1"); @@ -516,7 +516,7 @@ sub addToGroup { addTest("testrungcc/enum3a _GNUCC=1"); addTest("testrungcc/enum3b _GNUCC=1"); addTest("testrungcc/enum3c _GNUCC=1"); -addBadComment("testrungcc/enum3c", +addBadComment("testrungcc/enum3c", "Limitation. CIL constant folder doesn't consider x << y constant if y is strange (negative or bigger than #bits in x's type)"); addTest("testrungcc/enum3d _GNUCC=1"); addTest("testrungcc/enum3e _GNUCC=1"); @@ -530,7 +530,7 @@ sub addToGroup { if($win32) { - addTest("testrun/extern_init _MSVC=1"); + addTest("testrun/extern_init _MSVC=1"); addTest("testrun/msvc2 _MSVC=1"); addTest("testrun/msvc3 _MSVC=1"); addTest("testrun/msvc4 _MSVC=1"); @@ -549,7 +549,7 @@ sub addToGroup { addTest("test/duplicate "); addTest("testrun/simon6"); - + addTest("testrun/stringsize"); addTest("testrun/min "); @@ -587,7 +587,7 @@ sub addToGroup { addTest("test/sync-3 _GNUCC=1"); addTest("testrun/comparisons"); addTest("testrun/assign"); - + @@ -725,49 +725,50 @@ sub addToGroup { addTest("testrunc99/c99-predefined"); addTest("testrunc99/c99-struct"); addTest("testrunc99/c99-complex"); +addTest("testrunc99/c99-universal-character-names"); # ---------------- c-torture ------------- ## if we have the c-torture tests add them ## But only if the ctorture group was specfied my $ctorture = '/usr/local/src/gcc/gcc/testsuite/gcc.c-torture'; -if(-d $ctorture && +if(-d $ctorture && defined $TEST->{option}->{group} && grep { $_ eq 'ctorture'} @{$TEST->{option}->{group}}) { - + # Omit some tests because they use __complex__ my @omit = ('compile/20000804-1', 'compile/20001222-1', 'compile/941019-1', 'compile/981223-1', 'compile/991213-1', 'compile/20010605-2', - 'compile/960512-1', 'compile/complex-1', - 'compile/complex-2', 'compile/complex-4', + 'compile/960512-1', 'compile/complex-1', + 'compile/complex-2', 'compile/complex-4', 'compile/complex-5', 'execute/complex-2', 'execute/complex-5', - 'execute/960512-1', 'execute/complex-4', + 'execute/960512-1', 'execute/complex-4', 'execute/complex-1', 'execute/20010605-2'); # Also omit those with inner functions - push @omit, + push @omit, ('compile/951116-1', 'compile/920415-1', - 'execute/920415-1', 'compile/20010605-1', + 'execute/920415-1', 'compile/20010605-1', 'execute/20010605-1', 'compile/20011023-1', 'compile/20010903-2', 'execute/comp-goto-2', 'execute/nestfunc-2', 'execute/921215-1', 'execute/920428-2', 'execute/921017-1', - 'execute/nest-stdar-1', 'execute/nestfunc-3', 'execute/920501-7', - 'execute/920721-4', 'execute/920612-2', 'execute/20010209', + 'execute/nest-stdar-1', 'execute/nestfunc-3', 'execute/920501-7', + 'execute/920721-4', 'execute/920612-2', 'execute/20010209', 'execute/931002-1', 'execute/nestfunc-1', 'execute/20000822-1', 'compile/930506-2', 'execute/20010209-1'); - # Read the compile tests + # Read the compile tests my @tortures; - foreach my $tortdir ('compile', 'execute', 'compat') { - @tortures = - map { $_ =~ m|$ctorture/$tortdir/(.+)\.c|; $1 } + foreach my $tortdir ('compile', 'execute', 'compat') { + @tortures = + map { $_ =~ m|$ctorture/$tortdir/(.+)\.c|; $1 } (glob "$ctorture/$tortdir/*.c"); # Remove those that were produced in previous runs @tortures = grep { $_ !~ m|cil$| } @tortures; # Remove those that we know should fail - @tortures = grep { my $t = "$tortdir/$_"; + @tortures = grep { my $t = "$tortdir/$_"; ! grep { $_ =~ m|$t|} @omit } @tortures; foreach my $tst (@tortures) { - addTest("tort/$tortdir/$tst _GNUCC=1"); + addTest("tort/$tortdir/$tst _GNUCC=1"); $TEST->addGroups("tort/$tortdir/$tst", 'ctorture'); } } @@ -821,14 +822,14 @@ sub extraOptions { return ( @supopt, "--cildebug!", - "--noremake!", + "--noremake!", ); } sub extraHelpMessage { my($self) = @_; - + my ($scriptname, $extra) = $self->SUPER::extraHelpMessage(); return ("testcil", $extra . << "EOF"); @@ -836,7 +837,7 @@ sub extraHelpMessage { Additional arguments for SafeC test harness --cildebug Use the debug versions of everything (default is false) --noremake Does not try to remake the executable before each test. - (so that you can modify the sources while the test + (so that you can modify the sources while the test is running) Default log file is safec.log EOF From 2a61619ef640c6940fd234911b2cf749457dffba Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Thu, 5 Dec 2019 17:23:42 +0100 Subject: [PATCH 04/36] Add inlining test. References #9 --- test/Makefile | 7 +++++++ test/small1/combine-c99inline_1.c | 4 ++++ test/small1/combine-c99inline_2.c | 7 +++++++ test/testcil.pl | 2 ++ 4 files changed, 20 insertions(+) create mode 100644 test/small1/combine-c99inline_1.c create mode 100644 test/small1/combine-c99inline_2.c diff --git a/test/Makefile b/test/Makefile index b86e1d7f8..7b8fcea99 100644 --- a/test/Makefile +++ b/test/Makefile @@ -290,6 +290,13 @@ arcombine: mustbegcc cd $(SMALL1); ./matrix.exe +combinec99%: $(SMALL1)/combine-c99%_1.c + cd $(SMALL1); \ + $(CILLY) $(CFLAGS) -std=c99 --merge \ + $(notdir $(wildcard $(SMALL1)/combine-c99$*_[1-9].c)) \ + $(EXEOUT)combine-c99$*.exe + cd $(SMALL1); ./combine-c99$*.exe + # ww: Scott's structs-edg-stl.c example structs : mustbemanju cd /usr/src/big-examples/; $(CILLY) --nomerge \ diff --git a/test/small1/combine-c99inline_1.c b/test/small1/combine-c99inline_1.c new file mode 100644 index 000000000..644905b30 --- /dev/null +++ b/test/small1/combine-c99inline_1.c @@ -0,0 +1,4 @@ +#include "stdio.h" +void add(int x, int y) { + printf("Called non-inline\n"); +} diff --git a/test/small1/combine-c99inline_2.c b/test/small1/combine-c99inline_2.c new file mode 100644 index 000000000..521031bd3 --- /dev/null +++ b/test/small1/combine-c99inline_2.c @@ -0,0 +1,7 @@ +#include "stdio.h" +inline void add(int i, int j) { printf("Called inline\n"); } + +int main() { + add(4, 5); + return 0; +} diff --git a/test/testcil.pl b/test/testcil.pl index 781a64772..9828bb4ad 100644 --- a/test/testcil.pl +++ b/test/testcil.pl @@ -726,6 +726,8 @@ sub addToGroup { addTest("testrunc99/c99-struct"); addTest("testrunc99/c99-complex"); addTest("testrunc99/c99-universal-character-names"); +addTest("combinec99inline "); + # ---------------- c-torture ------------- ## if we have the c-torture tests add them From f119eb5a8974f7f6add15d26fe0ef355deb226b0 Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Fri, 13 Dec 2019 18:25:43 +0100 Subject: [PATCH 05/36] Fix pAtrr to correctly print _Complex types. References #9 --- src/cil.ml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/cil.ml b/src/cil.ml index 887c67475..9e49a38ad 100755 --- a/src/cil.ml +++ b/src/cil.ml @@ -4389,6 +4389,8 @@ class defaultCilPrinterClass : cilPrinter = object (self) match an, args with "const", [] -> text "const", false (* Put the aconst inside the attribute list *) + | "complex", [] when !c99Mode -> text "_Complex", false + | "complex", [] when not !msvcMode -> text "__complex__", false | "aconst", [] when not !msvcMode -> text "__const__", true | "thread", [] when not !msvcMode -> text "__thread", false (* From 1912efbcb8b76a1ff6de5a24ba4ff76cce80db5b Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Wed, 8 Jan 2020 14:30:33 +0100 Subject: [PATCH 06/36] gitignore vscode settings --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 6ee566b62..3aef1242e 100644 --- a/.gitignore +++ b/.gitignore @@ -392,3 +392,4 @@ _opam/ /test/small2/merge-ar /test/small2/libmerge.a /test/small2/*.o +.vscode/settings.json From 3f130da9bcc9d275a55f55869fc8d766d3a27fbf Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Fri, 10 Jan 2020 13:47:30 +0100 Subject: [PATCH 07/36] Add assertion to c99-complex test case --- test/small1/c99-complex.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/test/small1/c99-complex.c b/test/small1/c99-complex.c index cb90ae492..76c63c382 100644 --- a/test/small1/c99-complex.c +++ b/test/small1/c99-complex.c @@ -1,12 +1,18 @@ #include #include #include +#include "testharness.h" int main(void) { - double complex z1 = I * I; // imaginary unit squared + double complex z1 = 1.0iF + 0.5; // imaginary unit squared printf("I * I = %.1f%+.1fi\n", creal(z1), cimag(z1)); + double d = creal(z1); + + if(d != 0.5) + E(1); + double complex z2 = pow(I, 2); // imaginary unit squared printf("pow(I, 2) = %.1f%+.1fi\n", creal(z2), cimag(z2)); From 2f8624b0eaf6bca143819f670fea7d3be15cf406 Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Fri, 10 Jan 2020 14:35:55 +0100 Subject: [PATCH 08/36] Add example for broken tgmath --- test/Makefile | 2 +- test/small1/c99-tgmath.c | 9 +++++++++ test/testcil.pl | 1 + 3 files changed, 11 insertions(+), 1 deletion(-) create mode 100644 test/small1/c99-tgmath.c diff --git a/test/Makefile b/test/Makefile index 7b8fcea99..a71355146 100644 --- a/test/Makefile +++ b/test/Makefile @@ -196,7 +196,7 @@ testrun/% : $(SMALL1)/%.c testrunc99/% : $(SMALL1)/%.c cd $(SMALL1); $(CILLY) --nomerge --commPrintLn \ - $(CFLAGS) -std=c99 $(EXEOUT)$*.exe $*.c + $(CFLAGS) -std=c99 $(EXEOUT)$*.exe $*.c -lm cd $(SMALL1); ./$*.exe echo SUCCESS diff --git a/test/small1/c99-tgmath.c b/test/small1/c99-tgmath.c new file mode 100644 index 000000000..d40ed8ac8 --- /dev/null +++ b/test/small1/c99-tgmath.c @@ -0,0 +1,9 @@ +#include +#include +#include +#include "testharness.h" + +int main(void) +{ + float v = fabs(1.0f); +} diff --git a/test/testcil.pl b/test/testcil.pl index 9828bb4ad..20289dc4a 100644 --- a/test/testcil.pl +++ b/test/testcil.pl @@ -726,6 +726,7 @@ sub addToGroup { addTest("testrunc99/c99-struct"); addTest("testrunc99/c99-complex"); addTest("testrunc99/c99-universal-character-names"); +addTest("testrunc99/c99-tgmath"); addTest("combinec99inline "); From caac4f37a242f270035faead7f455727e29d4956 Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Tue, 14 Jan 2020 09:27:49 +0100 Subject: [PATCH 09/36] WIP Dirty: towards handeling complex and tgmath References #8, References #9 --- src/cil.ml | 23 ++++++++++++++++-- src/cil.mli | 4 +++- src/ext/llvm/llvmutils.ml | 3 +++ src/frontc/cabs.ml | 3 +++ src/frontc/cabs2cil.ml | 50 ++++++++++++++++++++++++++++++++------- src/frontc/clexer.mll | 7 +++++- src/frontc/cparser.mly | 14 ++++++++--- src/frontc/cprint.ml | 1 + 8 files changed, 90 insertions(+), 15 deletions(-) diff --git a/src/cil.ml b/src/cil.ml index 9e49a38ad..7e3bc0f4b 100755 --- a/src/cil.ml +++ b/src/cil.ml @@ -62,7 +62,7 @@ let cilVersionRevision = Cilversion.cilVersionRev let msvcMode = ref false (* Whether the pretty printer should * print output for the MS VC * compiler. Default is GCC *) -let c99Mode = ref false (* True to handle ISO C 99 vs 90 changes. +let c99Mode = ref true (* True to handle ISO C 99 vs 90 changes. (* TODO: This should be exposed *) So far only affects integer parsing. *) (* Set this to true to get old-style handling of gcc's extern inline C extension: @@ -292,6 +292,9 @@ and fkind = FFloat (** [float] *) | FDouble (** [double] *) | FLongDouble (** [long double] *) + | FComplexFloat + | FComplexDouble + | FComplexLongDouble (** An attribute has a name and some optional parameters *) and attribute = Attr of string * attrparam list @@ -1664,6 +1667,9 @@ let d_fkind () = function FFloat -> text "float" | FDouble -> text "double" | FLongDouble -> text "long double" + | FComplexFloat -> text "_Complex float" + | FComplexDouble -> text "_Complex double" + | FComplexLongDouble -> text "_Complex long double" let d_storage () = function NoStorage -> nil @@ -1751,7 +1757,10 @@ let d_const () c = (match fsize with FFloat -> chr 'f' | FDouble -> nil - | FLongDouble -> chr 'L') + | FLongDouble -> chr 'L' + | FComplexFloat -> text "iF" + | FComplexDouble -> chr 'i' + | FComplexLongDouble -> text "iL") | CEnum(_, s, ei) -> text s @@ -2154,6 +2163,9 @@ let rec alignOf_int t = | TFloat(FFloat, _) -> !M.theMachine.M.alignof_float | TFloat(FDouble, _) -> !M.theMachine.M.alignof_double | TFloat(FLongDouble, _) -> !M.theMachine.M.alignof_longdouble + | TFloat(FComplexFloat, _) -> !M.theMachine.M.alignof_float (* TODO! *) + | TFloat(FComplexDouble, _) -> !M.theMachine.M.alignof_double (* TODO! *) + | TFloat(FComplexLongDouble, _) -> !M.theMachine.M.alignof_longdouble (* TODO! *) | TNamed (t, _) -> alignOf_int t.ttype | TArray (t, _, _) -> alignOf_int t | TPtr _ | TBuiltin_va_list _ -> !M.theMachine.M.alignof_ptr @@ -2962,6 +2974,9 @@ let initGccBuiltins () : unit = H.add h "__builtin_ctzl" (intType, [ ulongType ], false); H.add h "__builtin_ctzll" (intType, [ ulongLongType ], false); + (* Do sth smart here, such as add a spurious cast to void *) + (* H.add h "__builtin_classify_type" (intType, [ voidType], false); *) + H.add h "__builtin_exp" (doubleType, [ doubleType ], false); H.add h "__builtin_expf" (floatType, [ floatType ], false); H.add h "__builtin_expl" (longDoubleType, [ longDoubleType ], false); @@ -3340,6 +3355,10 @@ class defaultCilPrinterClass : cilPrinter = object (self) (* variable declaration *) method pVDecl () (v:varinfo) = + (* These were treated as if they were functions but they are not *) + (* if v.vname = "__real__" || v.vname = "__imag__" then + nil + else *) let stom, rest = separateStorageModifiers v.vattr in (* First the storage modifiers *) text (if v.vinline then "__inline " else "") diff --git a/src/cil.mli b/src/cil.mli index c8c9676b7..99063af3f 100644 --- a/src/cil.mli +++ b/src/cil.mli @@ -293,7 +293,9 @@ and fkind = FFloat (** [float] *) | FDouble (** [double] *) | FLongDouble (** [long double] *) - + | FComplexFloat + | FComplexDouble + | FComplexLongDouble (** {b Attributes.} *) diff --git a/src/ext/llvm/llvmutils.ml b/src/ext/llvm/llvmutils.ml index 32585c735..2a4dec107 100644 --- a/src/ext/llvm/llvmutils.ml +++ b/src/ext/llvm/llvmutils.ml @@ -143,6 +143,9 @@ and gType (t:typ) : doc = match t with | TFloat (FFloat, _) -> text "float" | TFloat (FDouble, _) -> text "double" | TFloat (FLongDouble, _) -> text "fp128" +| TFloat (FComplexFloat, _) -> text "float" (* TODO: Incorrect *) +| TFloat (FComplexDouble, _) -> text "double" (* TODO: Incorrect *) +| TFloat (FComplexLongDouble, _) -> text "fp128" (* TODO: Incorrect *) | TPtr (t, _) -> (* LLVM uses "i8 *" for 'void *' *) if isVoidType t then text "i8 *" diff --git a/src/frontc/cabs.ml b/src/frontc/cabs.ml index 4865fe92a..16779e290 100644 --- a/src/frontc/cabs.ml +++ b/src/frontc/cabs.ml @@ -268,6 +268,8 @@ and expression = | CONSTANT of constant | PAREN of expression | VARIABLE of string + | REAL of expression + | IMAG of expression | EXPR_SIZEOF of expression | TYPE_SIZEOF of specifier * decl_type | EXPR_ALIGNOF of expression @@ -281,6 +283,7 @@ and expression = and constant = | CONST_INT of string (* the textual representation *) | CONST_FLOAT of string (* the textual representaton *) + | CONST_COMPLEX of string (* the textual representation *) | CONST_CHAR of int64 list | CONST_WCHAR of int64 list | CONST_STRING of string diff --git a/src/frontc/cabs2cil.ml b/src/frontc/cabs2cil.ml index 327948a2a..b6d2ffb9e 100644 --- a/src/frontc/cabs2cil.ml +++ b/src/frontc/cabs2cil.ml @@ -1256,11 +1256,17 @@ let arithmeticConversion (* c.f. ISO 6.3.1.8 *) (t2: typ) : typ = match unrollType t1, unrollType t2 with TFloat(FLongDouble, _), _ -> t1 + | TFloat(FComplexLongDouble, _), _ -> t1 | _, TFloat(FLongDouble, _) -> t2 + | _, TFloat(FComplexLongDouble, _) -> t2 | TFloat(FDouble, _), _ -> t1 + | TFloat(FComplexDouble, _), _ -> t1 | _, TFloat (FDouble, _) -> t2 + | _, TFloat (FComplexDouble, _) -> t2 | TFloat(FFloat, _), _ -> t1 + | TFloat(FComplexFloat, _), _ -> t1 | _, TFloat (FFloat, _) -> t2 + | _, TFloat (FComplexFloat, _) -> t2 | _, _ -> begin let t1' = integralPromotion t1 in let t2' = integralPromotion t2 in @@ -3446,11 +3452,10 @@ and doExp (asconst: bool) (* This expression is used as a constant *) finishExp se lv' field_type | A.CONSTANT ct -> begin - let hasSuffix str = + let hasSuffix str suffix = let l = String.length str in - fun s -> - let ls = String.length s in - l >= ls && s = String.uppercase_ascii (String.sub str (l - ls) ls) + let ls = String.length suffix in + l >= ls && String.uppercase_ascii suffix = String.uppercase_ascii (String.sub str (l - ls) ls) in match ct with A.CONST_INT str -> begin @@ -3533,13 +3538,12 @@ and doExp (asconst: bool) (* This expression is used as a constant *) | A.CONST_FLOAT str -> begin (* Maybe it ends in U or UL. Strip those *) let l = String.length str in - let hasSuffix = hasSuffix str in let baseint, kind = - if hasSuffix "L" then + if hasSuffix str "L" then String.sub str 0 (l - 1), FLongDouble - else if hasSuffix "F" then + else if hasSuffix str "F" then String.sub str 0 (l - 1), FFloat - else if hasSuffix "D" then + else if hasSuffix str "D" then String.sub str 0 (l - 1), FDouble else str, FDouble @@ -3561,6 +3565,36 @@ and doExp (asconst: bool) (* This expression is used as a constant *) finishExp empty res (typeOf res) end end + | A.CONST_COMPLEX str -> begin + (* Maybe it ends in U or UL. Strip those *) + let l = String.length str in + let baseint, kind = + if hasSuffix str "iL" then + String.sub str 0 (l - 2), FComplexLongDouble + else if hasSuffix str "iF" then + String.sub str 0 (l - 2), FComplexFloat + else if hasSuffix str "iD" then + String.sub str 0 (l - 2), FComplexDouble + else + str, FComplexDouble (* this is not ok *) + in + if kind = FLongDouble then + (* We only have 64-bit values in Ocaml *) + E.log "treating long double constant %s as double constant at %a.\n" + str d_loc !currentLoc; + try + finishExp empty + (Const(CReal(float_of_string baseint, kind, + Some str))) + (TFloat(kind,[])) + with e -> begin + ignore (E.log "float_of_string_2 %s (%s)\n" baseint + (Printexc.to_string e)); + E.hadErrors := true; + let res = Const(CStr "booo CONS_FLOAT") in + finishExp empty res (typeOf res) + end + end end | A.TYPE_SIZEOF (bt, dt) -> diff --git a/src/frontc/clexer.mll b/src/frontc/clexer.mll index e94a8d0be..51837997f 100644 --- a/src/frontc/clexer.mll +++ b/src/frontc/clexer.mll @@ -184,7 +184,8 @@ let init_lexicon _ = ("__alignof__", fun loc -> ALIGNOF loc); ("__volatile__", fun loc -> VOLATILE loc); ("__volatile", fun loc -> VOLATILE loc); - + ("__real__", fun loc -> REAL loc); + ("__imag__", fun loc -> IMAG loc); ("__FUNCTION__", fun loc -> FUNCTION__ loc); ("__func__", fun loc -> FUNCTION__ loc); (* ISO 6.4.2.2 *) ("__PRETTY_FUNCTION__", fun loc -> PRETTY_FUNCTION__ loc); @@ -436,6 +437,9 @@ let hexfloat = hexprefix hexfraction binexponent let floatsuffix = ['f' 'F' 'l' 'L'] let floatnum = (decfloat | hexfloat) floatsuffix? +let complexnum = (decfloat | hexfloat) ['i' 'I'] floatsuffix + + let ident = (letter|'_'|'$')(letter|decdigit|'_'|'$')* let blank = [' ' '\t' '\012' '\r']+ let escape = '\\' _ @@ -502,6 +506,7 @@ rule initial = ("wide string: " ^ Printexc.to_string e))} | floatnum {CST_FLOAT (Lexing.lexeme lexbuf, currentLoc ())} +| complexnum {CST_COMPLEX (Lexing.lexeme lexbuf, currentLoc ())} | hexnum {CST_INT (Lexing.lexeme lexbuf, currentLoc ())} | octnum {CST_INT (Lexing.lexeme lexbuf, currentLoc ())} | intnum {CST_INT (Lexing.lexeme lexbuf, currentLoc ())} diff --git a/src/frontc/cparser.mly b/src/frontc/cparser.mly index 635782065..672b1b903 100644 --- a/src/frontc/cparser.mly +++ b/src/frontc/cparser.mly @@ -246,6 +246,7 @@ let transformOffsetOf (speclist, dtype) member = %token CST_WCHAR %token CST_INT %token CST_FLOAT +%token CST_COMPLEX %token NAMED_TYPE /* Each character is its own list element, and the terminating nul is not @@ -291,7 +292,7 @@ let transformOffsetOf (speclist, dtype) member = %token IF TRY EXCEPT FINALLY %token ELSE -%token ATTRIBUTE INLINE ASM TYPEOF FUNCTION__ PRETTY_FUNCTION__ +%token ATTRIBUTE INLINE ASM TYPEOF REAL IMAG FUNCTION__ PRETTY_FUNCTION__ %token LABEL__ %token BUILTIN_VA_ARG ATTRIBUTE_USED %token BUILTIN_VA_LIST @@ -326,7 +327,7 @@ let transformOffsetOf (speclist, dtype) member = %left INF_INF SUP_SUP %left PLUS MINUS %left STAR SLASH PERCENT CONST RESTRICT VOLATILE COMPLEX HIDDEN -%right EXCLAM TILDE PLUS_PLUS MINUS_MINUS CAST RPAREN ADDROF SIZEOF ALIGNOF +%right EXCLAM TILDE PLUS_PLUS MINUS_MINUS CAST RPAREN ADDROF SIZEOF ALIGNOF IMAG REAL %left LBRACKET %left DOT ARROW LPAREN LBRACE %right NAMED_TYPE /* We'll use this to handle redefinitions of @@ -527,6 +528,10 @@ unary_expression: /*(* 6.5.3 *)*/ {EXPR_SIZEOF (fst $2), $1} | SIZEOF LPAREN type_name RPAREN {let b, d = $3 in TYPE_SIZEOF (b, d), $1} +| REAL cast_expression + {REAL (fst $2), $1} +| IMAG cast_expression + {IMAG (fst $2), $1} | ALIGNOF unary_expression {EXPR_ALIGNOF (fst $2), $1} | ALIGNOF LPAREN type_name RPAREN @@ -687,6 +692,7 @@ expression: /*(* 6.5.17 *)*/ constant: CST_INT {CONST_INT (fst $1), snd $1} | CST_FLOAT {CONST_FLOAT (fst $1), snd $1} +| CST_COMPLEX {CONST_COMPLEX (fst $1), snd $1} | CST_CHAR {CONST_CHAR (fst $1), snd $1} | CST_WCHAR {CONST_WCHAR (fst $1), snd $1} | string_constant {CONST_STRING (fst $1), snd $1} @@ -1405,7 +1411,9 @@ postfix_attr: * that their arguments be expressions, not attributes *)*/ unary_attr: postfix_attr { $1 } -| SIZEOF unary_expression {EXPR_SIZEOF (fst $2) } +| SIZEOF unary_expression { EXPR_SIZEOF (fst $2) } +| REAL unary_expression { REAL (fst $2) } +| IMAG unary_expression { IMAG (fst $2) } | SIZEOF LPAREN type_name RPAREN {let b, d = $3 in TYPE_SIZEOF (b, d)} diff --git a/src/frontc/cprint.ml b/src/frontc/cprint.ml index 79325b61d..3b76f323c 100644 --- a/src/frontc/cprint.ml +++ b/src/frontc/cprint.ml @@ -507,6 +507,7 @@ and print_expression_level (lvl: int) (exp : expression) = (match cst with CONST_INT i -> print i | CONST_FLOAT r -> print r + | CONST_COMPLEX r -> print r | CONST_CHAR c -> print ("'" ^ escape_wstring c ^ "'") | CONST_WCHAR c -> print ("L'" ^ escape_wstring c ^ "'") | CONST_STRING s -> print_string s From e1471d09d645b4d096b7ff8382e30b31b0ec7d36 Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Tue, 14 Jan 2020 13:31:08 +0100 Subject: [PATCH 10/36] Add Real (and Imag) to CIL and make connection with cabs References #8, References #9 --- src/check.ml | 11 +++++++++- src/cil.ml | 42 +++++++++++++++++++++++++++++++----- src/cil.mli | 6 +++++- src/ext/ccl/ccl.ml | 2 ++ src/ext/llvm/llvmgen.ml | 2 ++ src/ext/pta/ptranal.ml | 2 ++ src/ext/simplify/simplify.ml | 4 ++++ src/frontc/cabs2cil.ml | 6 +++++- src/frontc/cabsvisit.ml | 6 ++++++ src/frontc/cprint.ml | 10 +++++++++ 10 files changed, 83 insertions(+), 8 deletions(-) diff --git a/src/check.ml b/src/check.ml index e5bedb5a2..050eecd4f 100644 --- a/src/check.ml +++ b/src/check.ml @@ -173,6 +173,7 @@ type ctxType = * in a cast *) | CTSizeof (* In a sizeof *) | CTDecl (* In a typedef, or a declaration *) + | CTNumeric (* As an argument to __real__ or __imag__ *) let d_context () = function CTStruct -> text "CTStruct" @@ -184,6 +185,7 @@ let d_context () = function | CTExp -> text "CTExp" | CTSizeof -> text "CTSizeof" | CTDecl -> text "CTDecl" + | CTNumeric -> text "CTNumeric" (* Keep track of all tags that we use. For each tag remember also the info @@ -225,7 +227,9 @@ let rec checkType (t: typ) (ctx: ctxType) = (ignore(warn "sizeof(function) is not defined in MSVC."); false) else ctx = CTPtr || ctx = CTDecl || ctx = CTSizeof - | _ -> true + | TInt _ -> true + | TFloat _ -> true + | _ -> ctx <> CTNumeric in if not (checkContext t) then ignore (warn "Type (%a) used in wrong context. Expected context: %a" @@ -491,6 +495,11 @@ and checkExp (isconst: bool) (e: exp) : typ = | SizeOfStr s -> typeOf e + | Real e -> + let te = checkExp isconst e in + typeOfReal te + | Imag e -> E.s (E.bug "unimplemented") + | AlignOf(t) -> begin (* Sizeof cannot be applied to certain types *) checkType t CTSizeof; diff --git a/src/cil.ml b/src/cil.ml index 7e3bc0f4b..286b946c8 100755 --- a/src/cil.ml +++ b/src/cil.ml @@ -492,7 +492,8 @@ and exp = * not turned into a constant because * some transformations might want to * change types *) - + | Real of exp (** __real__() *) + | Imag of exp (** __imag__() *) | SizeOfE of exp (** sizeof() *) | SizeOfStr of string (** sizeof(string_literal). We separate this case out because this is the @@ -1596,6 +1597,21 @@ let isVoidPtrType t = TPtr(tau,_) when isVoidType tau -> true | _ -> false +(* get the typ of __real__(e) for e of typ t*) +let typeOfReal t = + match unrollType t with + | TInt _ -> t + | TFloat (fkind, attrs) -> + let newfkind = function + | FFloat -> FFloat (** [float] *) + | FDouble -> FDouble (** [double] *) + | FLongDouble -> FLongDouble (** [long double] *) + | FComplexFloat -> FFloat + | FComplexDouble -> FDouble + | FComplexLongDouble -> FLongDouble + in TFloat (newfkind fkind, attrs) + | _ -> E.s (E.bug "unexpected non-numerical type for argument to __real__") + let var vi : lval = (Var vi, NoOffset) (* let assign vi e = Instrs(Set (var vi, e), lu) *) @@ -1798,6 +1814,8 @@ let getParenthLevel (e: exp) = | BinOp((Div|Mod|Mult),_,_,_) -> 40 (* Unary *) + | Real _ -> 30 + | Imag _ -> 30 | CastE(_,_) -> 30 | AddrOf(_) -> 30 | AddrOfLabel(_) -> 30 @@ -1892,7 +1910,8 @@ let rec typeOf (e: exp) : typ = | Const(CReal (_, fk, _)) -> TFloat(fk, []) | Const(CEnum(tag, _, ei)) -> typeOf tag - + | Real e -> typeOfReal @@ typeOf e + | Imag e -> E.s (E.bug "unsupported") | Lval(lv) -> typeOfLval lv | SizeOf _ | SizeOfE _ | SizeOfStr _ -> !typeOfSizeOf | AlignOf _ | AlignOfE _ -> !typeOfSizeOf @@ -2755,6 +2774,8 @@ let rec isConstant = function | Lval (Var vi, NoOffset) -> (vi.vglob && isArrayType vi.vtype || isFunctionType vi.vtype) | Lval _ -> false + | Real e -> isConstant e + | Imag e -> isConstant e | SizeOf _ | SizeOfE _ | SizeOfStr _ | AlignOf _ | AlignOfE _ -> true | CastE (_, e) -> isConstant e | AddrOf (Var vi, off) | StartOf (Var vi, off) @@ -3432,7 +3453,10 @@ class defaultCilPrinterClass : cilPrinter = object (self) text "__builtin_va_arg_pack()" | SizeOfE (e) -> text "sizeof(" ++ self#pExp () e ++ chr ')' - + | Imag e -> + text "__imag__(" ++ self#pExp () e ++ chr ')' + | Real e -> + text "__real__(" ++ self#pExp () e ++ chr ')' | SizeOfStr s -> text "sizeof(" ++ d_const () (CStr s) ++ chr ')' @@ -4800,7 +4824,10 @@ class plainCilPrinterClass = text "__alignof__(" ++ self#pType None () t ++ chr ')' | AlignOfE (e) -> text "__alignof__(" ++ self#pExp () e ++ chr ')' - + | Imag e -> + text "__imag__(" ++ self#pExp () e ++ chr ')' + | Real e -> + text "__real__(" ++ self#pExp () e ++ chr ')' | StartOf lv -> dprintf "StartOf(%a)" self#pLval lv | AddrOf (lv) -> dprintf "AddrOf(%a)" self#pLval lv | AddrOfLabel (sref) -> dprintf "AddrOfLabel(%a)" self#pStmt !sref @@ -5283,7 +5310,12 @@ and childrenExp (vis: cilVisitor) (e: exp) : exp = let e1' = vExp e1 in if e1' != e1 then SizeOfE e1' else e | SizeOfStr s -> e - + | Real e1 -> + let e1' = vExp e1 in + if e1' != e1 then Real e1' else e + | Imag e1 -> + let e1' = vExp e1 in + if e1' != e1 then Imag e1' else e | AlignOf t -> let t' = vTyp t in if t' != t then AlignOf t' else e diff --git a/src/cil.mli b/src/cil.mli index 99063af3f..7d54a9d42 100644 --- a/src/cil.mli +++ b/src/cil.mli @@ -586,7 +586,8 @@ and exp = (** sizeof(). Has [unsigned int] type (ISO 6.5.3.4). This is not * turned into a constant because some transformations might want to * change types *) - + | Real of exp (** __real__() *) + | Imag of exp (** __imag__() *) | SizeOfE of exp (** sizeof() *) @@ -1323,6 +1324,9 @@ val isVoidType: typ -> bool (** is the given type "void *"? *) val isVoidPtrType: typ -> bool +(** for numerical __complex types return type of corresponding real part *) +val typeOfReal: typ -> typ + (** int *) val intType: typ diff --git a/src/ext/ccl/ccl.ml b/src/ext/ccl/ccl.ml index 9ea66836c..01f733aa3 100644 --- a/src/ext/ccl/ccl.ml +++ b/src/ext/ccl/ccl.ml @@ -1078,6 +1078,8 @@ let rec evaluateExp (e : exp) (state : state) : summary = | StartOf lv -> evaluateLval lv state | Question _ -> E.s (E.unimp "ternary operator ?:") | AddrOfLabel _ -> E.s (E.unimp "address of label") + | Real _ -> E.s (E.unimp "real") + | Imag _ -> E.s (E.unimp "imag") and evaluateLval (lv : lval) (state : state) : summary = match lv with diff --git a/src/ext/llvm/llvmgen.ml b/src/ext/llvm/llvmgen.ml index 1db61bfb5..1a1cf4ad0 100644 --- a/src/ext/llvm/llvmgen.ml +++ b/src/ext/llvm/llvmgen.ml @@ -1000,6 +1000,8 @@ class llvmGeneratorClass : llvmGenerator = object (self) | CastE (t, e) -> iCast t e | AddrOf lv -> iAddrOf lv | StartOf lv -> iStartOf lv + | Imag e -> raise (Unimplemented "Imag") + | Real e -> raise (Unimplemented "Real") | AddrOfLabel _ -> raise (Unimplemented "AddrOfLabel") | Question _ -> raise (Unimplemented "Question") diff --git a/src/ext/pta/ptranal.ml b/src/ext/pta/ptranal.ml index f13a3ad1e..af1defb11 100644 --- a/src/ext/pta/ptranal.ml +++ b/src/ext/pta/ptranal.ml @@ -255,6 +255,8 @@ and analyze_expr (e : exp ) : A.tau = | StartOf l -> A.address (analyze_lval l) | AlignOfE _ -> A.bottom () | SizeOfE _ -> A.bottom () + | Imag __ -> failwith "not implemented yet" + | Real __ -> failwith "not implemented yet" in H.add expressions e result; result diff --git a/src/ext/simplify/simplify.ml b/src/ext/simplify/simplify.ml index 182da9870..f5d178956 100644 --- a/src/ext/simplify/simplify.ml +++ b/src/ext/simplify/simplify.ml @@ -131,6 +131,10 @@ let rec makeThreeAddress BinOp(bo, makeBasic setTemp e1, makeBasic setTemp e2, tres) | Question _ -> E.s (bug "Simplify: There should not be a \"?:\" operator here.") + | Real e1 -> + Real (makeBasic setTemp e1) + | Imag e1 -> + Imag (makeBasic setTemp e1) | UnOp(uo, e1, tres) -> UnOp(uo, makeBasic setTemp e1, tres) | CastE(t, e) -> diff --git a/src/frontc/cabs2cil.ml b/src/frontc/cabs2cil.ml index b6d2ffb9e..b2d8154f6 100644 --- a/src/frontc/cabs2cil.ml +++ b/src/frontc/cabs2cil.ml @@ -3641,7 +3641,11 @@ and doExp (asconst: bool) (* This expression is used as a constant *) | _ -> SizeOfE e' in finishExp empty size !typeOfSizeOf - + | A.REAL e -> + let (se, e', t) = doExp false e (AExp None) in + let real = Real e' in + finishExp se real (typeOfReal t) + | A.IMAG e -> E.s (bug "cabs2cil: unsupported") | A.TYPE_ALIGNOF (bt, dt) -> let typ = doOnlyType bt dt in finishExp empty (AlignOf(typ)) !typeOfSizeOf diff --git a/src/frontc/cabsvisit.ml b/src/frontc/cabsvisit.ml index 636cd2a78..21204dacc 100644 --- a/src/frontc/cabsvisit.ml +++ b/src/frontc/cabsvisit.ml @@ -506,6 +506,12 @@ and childrenExpression vis e = | EXPR_SIZEOF (e1) -> let e1' = ve e1 in if e1' != e1 then EXPR_SIZEOF (e1') else e + | REAL e1 -> + let e1' = ve e1 in + if e1' != e1 then REAL (e1') else e + | IMAG e1 -> + let e1' = ve e1 in + if e1' != e1 then IMAG (e1') else e | TYPE_SIZEOF (s, dt) -> let s' = visitCabsSpecifier vis s in let dt' = visitCabsDeclType vis false dt in diff --git a/src/frontc/cprint.ml b/src/frontc/cprint.ml index 3b76f323c..9dfe05c2c 100644 --- a/src/frontc/cprint.ml +++ b/src/frontc/cprint.ml @@ -403,6 +403,8 @@ and get_operator exp = | TYPE_SIZEOF _ -> ("", 16) | EXPR_ALIGNOF exp -> ("", 16) | TYPE_ALIGNOF _ -> ("", 16) + | IMAG exp -> ("", 16) + | REAL exp -> ("", 16) | INDEX (exp, idx) -> ("", 15) | MEMBEROF (exp, fld) -> ("", 15) | MEMBEROFPTR (exp, fld) -> ("", 15) @@ -530,6 +532,14 @@ and print_expression_level (lvl: int) (exp : expression) = printl ["__alignof__";"("]; print_onlytype (bt, dt); print ")" + | IMAG exp -> + printl ["__imag__";"("]; + print_expression_level 0 exp; + print ")" + | REAL exp -> + printl ["__real__";"("]; + print_expression_level 0 exp; + print ")" | INDEX (exp, idx) -> print_expression_level 16 exp; print "["; From 4bbbed73e33744db61a871c4608228e2b3ac9142 Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Tue, 14 Jan 2020 13:43:15 +0100 Subject: [PATCH 11/36] Extend tgmath.h test --- test/small1/c99-tgmath.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/test/small1/c99-tgmath.c b/test/small1/c99-tgmath.c index d40ed8ac8..ff2b003d2 100644 --- a/test/small1/c99-tgmath.c +++ b/test/small1/c99-tgmath.c @@ -1,9 +1,21 @@ #include #include -#include #include "testharness.h" int main(void) { - float v = fabs(1.0f); + float f = fabs(1.0f); + double d = fabs(1.0); + long l = fabs(1.0l); + + if(f != 1.0f) + E(1); + + if(d != 1.0) + E(2); + + if(l != 1.0l) + E(3); + + return 0; } From 398c70f71648b97012abdbe29e6a473782a63638 Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Wed, 15 Jan 2020 13:05:34 +0100 Subject: [PATCH 12/36] Fix compiler warning from clexer.mll --- src/frontc/clexer.mll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/frontc/clexer.mll b/src/frontc/clexer.mll index 51837997f..4b117700c 100644 --- a/src/frontc/clexer.mll +++ b/src/frontc/clexer.mll @@ -623,7 +623,7 @@ and hash = parse let s = Lexing.lexeme lexbuf in let lineno = try int_of_string s - with Failure ("int_of_string") -> + with Failure _ -> (* the int is too big. *) E.warn "Bad line number in preprocessed file: %s" s; (-1) From 38e42780bcd43ecffa8a31183b2d10c1f08c504b Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Wed, 15 Jan 2020 13:23:23 +0100 Subject: [PATCH 13/36] Add isNullPtrConstant to determine if a CIL expression is a nullPtrConstant --- src/cil.ml | 6 ++++++ src/cil.mli | 3 +++ 2 files changed, 9 insertions(+) diff --git a/src/cil.ml b/src/cil.ml index 286b946c8..f7c9ff059 100755 --- a/src/cil.ml +++ b/src/cil.ml @@ -2766,6 +2766,12 @@ let isArrayType t = TArray _ -> true | _ -> false +(** 6.3.2.3 subsection 3 *) +(** An integer constant expr with value 0, or such an expr cast to void *, is called a null pointer constant. *) +let isNullPtrConstant = function + | CastE(TPtr(TVoid _,_), e) -> isZero @@ constFold true e + | e -> isZero @@ constFold true e + let rec isConstant = function | Const _ -> true | UnOp (_, e, _) -> isConstant e diff --git a/src/cil.mli b/src/cil.mli index 7d54a9d42..c332b220c 100644 --- a/src/cil.mli +++ b/src/cil.mli @@ -1657,6 +1657,9 @@ val isConstantOffset: offset -> bool constant with value zero *) val isZero: exp -> bool +(** True if the given expression is a null-pointer constant. As per 6.3.2.3 subsection 3 *) +val isNullPtrConstant: exp -> bool + (** Given the character c in a (CChr c), sign-extend it to 32 bits. (This is the official way of interpreting character constants, according to ISO C 6.4.4.4.10, which says that character constants are chars cast to ints) From 60251ce6a4acc3d217b32d083f16730f81c1221c Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Wed, 15 Jan 2020 13:58:25 +0100 Subject: [PATCH 14/36] Fix conditionalConversion to conform to ISO 6.5.15 Is needed for support for tgmath.h --- src/frontc/cabs2cil.ml | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/src/frontc/cabs2cil.ml b/src/frontc/cabs2cil.ml index b2d8154f6..013ed4e01 100644 --- a/src/frontc/cabs2cil.ml +++ b/src/frontc/cabs2cil.ml @@ -1873,24 +1873,26 @@ let makeGlobalVarinfo (isadef: bool) (vi: varinfo) : varinfo * bool = alphaConvertVarAndAddToEnv true vi, false end -let conditionalConversion (t2: typ) (t3: typ) : typ = +let conditionalConversion (t2: typ) (t3: typ) (e2: exp option) (e3:exp) : typ = let tresult = (* ISO 6.5.15 *) - match unrollType t2, unrollType t3 with + match unrollType t2, unrollType t3, e2 with (TInt _ | TEnum _ | TFloat _), - (TInt _ | TEnum _ | TFloat _) -> + (TInt _ | TEnum _ | TFloat _), _ -> arithmeticConversion t2 t3 - | TComp (comp2,_), TComp (comp3,_) + | TComp (comp2,_), TComp (comp3,_), _ when comp2.ckey = comp3.ckey -> t2 - | TPtr(_, _), TPtr(TVoid _, _) -> t2 - | TPtr(TVoid _, _), TPtr(_, _) -> t3 - | TPtr _, TPtr _ when Util.equals (typeSig t2) (typeSig t3) -> t2 - | TPtr _, TInt _ -> t2 (* most likely comparison with 0 *) - | TInt _, TPtr _ -> t3 (* most likely comparison with 0 *) + | TPtr(_, _), TPtr(TVoid _, _), _ -> + if isNullPtrConstant e3 then t2 else t3 + | TPtr(TVoid _, _), TPtr(_, _), Some e2' -> + if isNullPtrConstant e2' then t3 else t2 + | TPtr _, TPtr _, _ when Util.equals (typeSig t2) (typeSig t3) -> t2 + | TPtr _, TInt _, _ -> t2 (* most likely comparison with int constant 0, if it isn't it would not be valid C *) + | TInt _, TPtr _, _ -> t3 (* most likely comparison with int constant 0, if it isn't it would not be valid C *) (* When we compare two pointers of different type, we combine them * using the same algorithm when combining multiple declarations of * a global *) - | (TPtr _) as t2', (TPtr _ as t3') -> begin + | (TPtr _) as t2', (TPtr _ as t3'), _ -> begin try combineTypes CombineOther t2' t3' with Failure msg -> begin ignore (warn "A.QUESTION: %a does not match %a (%s)" @@ -1898,7 +1900,7 @@ let conditionalConversion (t2: typ) (t3: typ) : typ = t2 (* Just pick one *) end end - | _, _ -> E.s (error "A.QUESTION for invalid combination of types") + | _, _,_ -> E.s (error "A.QUESTION for invalid combination of types") in tresult @@ -4541,22 +4543,22 @@ and doExp (asconst: bool) (* This expression is used as a constant *) let ce1 = doCondExp asconst e1 in (* Now we must find the type of both branches, in order to compute * the type of the result *) - let se2, e2'o (* is an option. None means use e1 *), t2 = + let se2, e2'o (* is an option. None means use e1 *), e_of_t2, t2 = match e2 with A.NOTHING -> begin (* The same as the type of e1 *) match ce1 with - CEExp (_, e1') -> empty, None, typeOf e1' (* Do not promote + CEExp (_, e1') -> empty, None, Some e1', typeOf e1' (* Do not promote to bool *) - | _ -> empty, None, intType + | _ -> empty, None, None, intType end | _ -> let se2, e2', t2 = doExp asconst e2 (AExp None) in - se2, Some e2', t2 + se2, Some e2', Some e2', t2 in (* Do e3 for real *) let se3, e3', t3 = doExp asconst e3 (AExp None) in (* Compute the type of the result *) - let tresult = conditionalConversion t2 t3 in + let tresult = conditionalConversion t2 t3 e_of_t2 e3' in match ce1 with CEExp (se1, e1') when isConstFalse e1' && canDrop se2 -> finishExp (se1 @@ se3) (snd (castTo t3 tresult e3')) tresult From 60d08510dd5ec9a578d96b4c40f7806c9c80414d Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Wed, 15 Jan 2020 14:22:33 +0100 Subject: [PATCH 15/36] Special treatment of __builtin_classify_type Add special treatment of __builtin_classify_type to Cabs, just like for example for __typeof__. Turn into CLASSIFYTYPE, and in cabs2cil.ml evaluate it to the appropriate int constant that GCC also uses. This is necessary to be able to determine the correct type of the conditional expressions used for tgmath.h. The correct type for an expression such as 0 ? (float *) 0 : (void*) (__builtin_classify_type(...) == X) depends on whether the last argument is a null pointer constant. `(void*) (__builtin_classify_type(...) == X)` is a nullptr constant iff `__builtin_classify_type(...) == X` is zero. To determine this it is neccessary to evaluate __bulitin_classify_type(...). --- src/frontc/cabs.ml | 1 + src/frontc/cabs2cil.ml | 31 +++++++++++++++++++++++++++++++ src/frontc/cabsvisit.ml | 3 +++ src/frontc/clexer.mll | 1 + src/frontc/cparser.mly | 7 +++++-- src/frontc/cprint.ml | 6 ++++++ 6 files changed, 47 insertions(+), 2 deletions(-) diff --git a/src/frontc/cabs.ml b/src/frontc/cabs.ml index 16779e290..d1deb7d3b 100644 --- a/src/frontc/cabs.ml +++ b/src/frontc/cabs.ml @@ -270,6 +270,7 @@ and expression = | VARIABLE of string | REAL of expression | IMAG of expression + | CLASSIFYTYPE of expression | EXPR_SIZEOF of expression | TYPE_SIZEOF of specifier * decl_type | EXPR_ALIGNOF of expression diff --git a/src/frontc/cabs2cil.ml b/src/frontc/cabs2cil.ml index 013ed4e01..9ab4eb9b1 100644 --- a/src/frontc/cabs2cil.ml +++ b/src/frontc/cabs2cil.ml @@ -3648,6 +3648,37 @@ and doExp (asconst: bool) (* This expression is used as a constant *) let real = Real e' in finishExp se real (typeOfReal t) | A.IMAG e -> E.s (bug "cabs2cil: unsupported") + | A.CLASSIFYTYPE e -> + let classify_type t = + match unrollTypeDeep t with (* See gcc/typeclass.h *) + | TVoid _ -> 0 + | TInt (ikind, _) ->begin + match ikind with + | IChar -> 2 + | IBool -> 4 + | _ -> 1 + end + | TFloat (fkind, _) -> begin + match fkind with + | FFloat + | FDouble + | FLongDouble -> 8 + | FComplexFloat + | FComplexDouble + | FComplexLongDouble -> 9 + end + | TEnum _ -> 3 + | TPtr _ -> 5 + | TArray _ -> 14 + | TFun _ -> 10 + | _ -> E.s (E.bug "cabs2cil: failed to classify for __builtin_classify_type") +(* no_type_class = -1, void_type_class 0, integer_type_class 1, char_type_class 2, enumeral_type_class 3, boolean_type_class 4, + pointer_type_class 5, reference_type_class 6, offset_type_class 7, real_type_class 8, + complex_type_class 9, function_type_class 10, method_type_class 11, record_type_class 12, union_type_class 13, array_type_class 14, string_type_class 15, lang_type_class 16 *) + in + let _,_, t = doExp true e (AType) in + let res = Cil.integer (classify_type t) in + finishExp empty (res) (Cil.typeOf res) | A.TYPE_ALIGNOF (bt, dt) -> let typ = doOnlyType bt dt in finishExp empty (AlignOf(typ)) !typeOfSizeOf diff --git a/src/frontc/cabsvisit.ml b/src/frontc/cabsvisit.ml index 21204dacc..d111896fb 100644 --- a/src/frontc/cabsvisit.ml +++ b/src/frontc/cabsvisit.ml @@ -512,6 +512,9 @@ and childrenExpression vis e = | IMAG e1 -> let e1' = ve e1 in if e1' != e1 then IMAG (e1') else e + | CLASSIFYTYPE e1 -> + let e1' = ve e1 in + if e1' != e1 then CLASSIFYTYPE (e1') else e | TYPE_SIZEOF (s, dt) -> let s' = visitCabsSpecifier vis s in let dt' = visitCabsDeclType vis false dt in diff --git a/src/frontc/clexer.mll b/src/frontc/clexer.mll index 4b117700c..6985b6da1 100644 --- a/src/frontc/clexer.mll +++ b/src/frontc/clexer.mll @@ -186,6 +186,7 @@ let init_lexicon _ = ("__volatile", fun loc -> VOLATILE loc); ("__real__", fun loc -> REAL loc); ("__imag__", fun loc -> IMAG loc); + ("__builtin_classify_type", fun loc -> CLASSIFYTYPE loc); ("__FUNCTION__", fun loc -> FUNCTION__ loc); ("__func__", fun loc -> FUNCTION__ loc); (* ISO 6.4.2.2 *) ("__PRETTY_FUNCTION__", fun loc -> PRETTY_FUNCTION__ loc); diff --git a/src/frontc/cparser.mly b/src/frontc/cparser.mly index 672b1b903..f5cbd24b2 100644 --- a/src/frontc/cparser.mly +++ b/src/frontc/cparser.mly @@ -292,7 +292,7 @@ let transformOffsetOf (speclist, dtype) member = %token IF TRY EXCEPT FINALLY %token ELSE -%token ATTRIBUTE INLINE ASM TYPEOF REAL IMAG FUNCTION__ PRETTY_FUNCTION__ +%token ATTRIBUTE INLINE ASM TYPEOF REAL IMAG FUNCTION__ PRETTY_FUNCTION__ CLASSIFYTYPE %token LABEL__ %token BUILTIN_VA_ARG ATTRIBUTE_USED %token BUILTIN_VA_LIST @@ -327,7 +327,7 @@ let transformOffsetOf (speclist, dtype) member = %left INF_INF SUP_SUP %left PLUS MINUS %left STAR SLASH PERCENT CONST RESTRICT VOLATILE COMPLEX HIDDEN -%right EXCLAM TILDE PLUS_PLUS MINUS_MINUS CAST RPAREN ADDROF SIZEOF ALIGNOF IMAG REAL +%right EXCLAM TILDE PLUS_PLUS MINUS_MINUS CAST RPAREN ADDROF SIZEOF ALIGNOF IMAG REAL CLASSIFYTYPE %left LBRACKET %left DOT ARROW LPAREN LBRACE %right NAMED_TYPE /* We'll use this to handle redefinitions of @@ -532,6 +532,8 @@ unary_expression: /*(* 6.5.3 *)*/ {REAL (fst $2), $1} | IMAG cast_expression {IMAG (fst $2), $1} +| CLASSIFYTYPE cast_expression + {CLASSIFYTYPE (fst $2), $1} | ALIGNOF unary_expression {EXPR_ALIGNOF (fst $2), $1} | ALIGNOF LPAREN type_name RPAREN @@ -1414,6 +1416,7 @@ unary_attr: | SIZEOF unary_expression { EXPR_SIZEOF (fst $2) } | REAL unary_expression { REAL (fst $2) } | IMAG unary_expression { IMAG (fst $2) } +| CLASSIFYTYPE unary_expression { CLASSIFYTYPE (fst $2) } | SIZEOF LPAREN type_name RPAREN {let b, d = $3 in TYPE_SIZEOF (b, d)} diff --git a/src/frontc/cprint.ml b/src/frontc/cprint.ml index 9dfe05c2c..c47e0ebe8 100644 --- a/src/frontc/cprint.ml +++ b/src/frontc/cprint.ml @@ -405,6 +405,7 @@ and get_operator exp = | TYPE_ALIGNOF _ -> ("", 16) | IMAG exp -> ("", 16) | REAL exp -> ("", 16) + | CLASSIFYTYPE exp -> ("", 16) | INDEX (exp, idx) -> ("", 15) | MEMBEROF (exp, fld) -> ("", 15) | MEMBEROFPTR (exp, fld) -> ("", 15) @@ -503,6 +504,11 @@ and print_expression_level (lvl: int) (exp : expression) = print "("; print_comma_exps args; print ")" + | CLASSIFYTYPE exp -> + print "__builtin_classify_type"; + print "("; + print_expression_level 1 exp; + print ")" | COMMA exps -> print_comma_exps exps | CONSTANT cst -> From 9a62a24e6d945330baa8a96cae30da6d4c2c45dc Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Wed, 15 Jan 2020 15:51:06 +0100 Subject: [PATCH 16/36] Also drop complex attribute in typeOfReal --- src/cil.ml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/cil.ml b/src/cil.ml index f7c9ff059..1e387d4dc 100755 --- a/src/cil.ml +++ b/src/cil.ml @@ -1609,7 +1609,9 @@ let typeOfReal t = | FComplexFloat -> FFloat | FComplexDouble -> FDouble | FComplexLongDouble -> FLongDouble - in TFloat (newfkind fkind, attrs) + in + let newattrs = dropAttribute "complex" attrs in + TFloat (newfkind fkind, newattrs) | _ -> E.s (E.bug "unexpected non-numerical type for argument to __real__") let var vi : lval = (Var vi, NoOffset) @@ -3001,9 +3003,6 @@ let initGccBuiltins () : unit = H.add h "__builtin_ctzl" (intType, [ ulongType ], false); H.add h "__builtin_ctzll" (intType, [ ulongLongType ], false); - (* Do sth smart here, such as add a spurious cast to void *) - (* H.add h "__builtin_classify_type" (intType, [ voidType], false); *) - H.add h "__builtin_exp" (doubleType, [ doubleType ], false); H.add h "__builtin_expf" (floatType, [ floatType ], false); H.add h "__builtin_expl" (longDoubleType, [ longDoubleType ], false); From f6cce9263111d48db7eb7d3471f8613eb275e740 Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Wed, 15 Jan 2020 16:03:04 +0100 Subject: [PATCH 17/36] Expand test for c99-complex.c --- test/small1/c99-complex.c | 217 +++++++++++++++++++++++++++++++++++++- 1 file changed, 213 insertions(+), 4 deletions(-) diff --git a/test/small1/c99-complex.c b/test/small1/c99-complex.c index 76c63c382..9da6b0e77 100644 --- a/test/small1/c99-complex.c +++ b/test/small1/c99-complex.c @@ -3,17 +3,34 @@ #include #include "testharness.h" +void forlong() { + long double complex z1 = 1.0il + 1; + printf("I * I = %.1Lf%+.1Lfi\n", creal(z1), cimag(z1)); + + long double complex z2 = pow(_Complex_I, 2); // imaginary unit squared + printf("pow(I, 2) = %.1Lf%+.1Lfi\n", creal(z2), cimag(z2)); + + double long PI = acos(-1); + double long complex z3 = exp(I * PI); // Euler's formula + printf("exp(I*PI) = %.1Lf%+.1Lfi\n", creal(z3), cimag(z3)); + + double long complex z4 = 1+2*I, z5 = 1-2*I; // conjugates + printf("(1+2i)*(1-2i) = %.Lf%+.Lfi\n", creal(z4*z5), cimag(z4*z5)); +} + int main(void) { - double complex z1 = 1.0iF + 0.5; // imaginary unit squared - printf("I * I = %.1f%+.1fi\n", creal(z1), cimag(z1)); + double complex x1 = 1.0iF + 0.5; - double d = creal(z1); + double d = creal(x1); if(d != 0.5) E(1); - double complex z2 = pow(I, 2); // imaginary unit squared + double complex z1 = 1.0iF + 1; + printf("I * I = %.1f%+.1fi\n", creal(z1), cimag(z1)); + + double complex z2 = pow(_Complex_I, 2); // imaginary unit squared printf("pow(I, 2) = %.1f%+.1fi\n", creal(z2), cimag(z2)); double PI = acos(-1); @@ -22,4 +39,196 @@ int main(void) double complex z4 = 1+2*I, z5 = 1-2*I; // conjugates printf("(1+2i)*(1-2i) = %.1f%+.1fi\n", creal(z4*z5), cimag(z4*z5)); + + forlong(); + return 0; +} + +void parsedebug() { + __real__ (1.0iF); + __real__ (2); + 0 + __real__(2); + __real__(2) + 0; + (sizeof (__real__ (1.0iF) + __real__ (2)) > sizeof (double) && __builtin_classify_type (__real__ (1.0iF) + __real__ (2)) == 8); + + + (__extension__ ((sizeof (__real__ (1.0iF) + __real__ (2)) > sizeof (double) && __builtin_classify_type (__real__ ( + + 1.0iF + + ) + __real__ ( + + 2 + + )) == 8) ? ((__builtin_classify_type (( + + 1.0iF + ) + ( + + 2 + + )) != 9) ? (__typeof ((__typeof__ (*(0 ? (__typeof__ (0 ? (__typeof__ ((__typeof__ (+( + + 1.0iF + + ))) 0) *) 0 : (void *) (!((__builtin_classify_type (__real__ ((__typeof__ (+( + 1.0iF + ))) 0)) == 8))))) 0 : (__typeof__ (0 ? (__typeof__ (0 ? (double *) 0 : (void *) (!((__builtin_classify_type ((__typeof__ (+( + 1.0iF + ))) 0) == 1))))) 0 : (__typeof__ (0 ? (_Complex double *) 0 : (void *) (!((__builtin_classify_type ((__typeof__ (+( + 1.0iF + ))) 0) == 9 && __builtin_classify_type (__real__ ((__typeof__ (+( + 1.0iF + ))) 0)) == 1))))) 0)) 0))) 0 + (__typeof__ (*(0 ? (__typeof__ (0 ? (__typeof__ ((__typeof__ (+( + 2 + ))) 0) *) 0 : (void *) (!((__builtin_classify_type (__real__ ((__typeof__ (+( + 2 + ))) 0)) == 8))))) 0 : (__typeof__ (0 ? (__typeof__ (0 ? (double *) 0 : (void *) (!((__builtin_classify_type ((__typeof__ (+( + 2 + ))) 0) == 1))))) 0 : (__typeof__ (0 ? (_Complex double *) 0 : (void *) (!((__builtin_classify_type ((__typeof__ (+( + 2 + ))) 0) == 9 && __builtin_classify_type (__real__ ((__typeof__ (+( + 2 + ))) 0)) == 1))))) 0)) 0))) 0)) powl ( + 1.0iF + , + 2 + ) : (__typeof ((__typeof__ (*(0 ? (__typeof__ (0 ? (__typeof__ ((__typeof__ (+( + 1.0iF + ))) 0) *) 0 : (void *) (!((__builtin_classify_type (__real__ ((__typeof__ (+( + 1.0iF + ))) 0)) == 8))))) 0 : (__typeof__ (0 ? (__typeof__ (0 ? (double *) 0 : (void *) (!((__builtin_classify_type ((__typeof__ (+( + 1.0iF + ))) 0) == 1))))) 0 : (__typeof__ (0 ? (_Complex double *) 0 : (void *) (!((__builtin_classify_type ((__typeof__ (+( + 1.0iF + ))) 0) == 9 && __builtin_classify_type (__real__ ((__typeof__ (+( + 1.0iF + ))) 0)) == 1))))) 0)) 0))) 0 + (__typeof__ (*(0 ? (__typeof__ (0 ? (__typeof__ ((__typeof__ (+( + 2 + ))) 0) *) 0 : (void *) (!((__builtin_classify_type (__real__ ((__typeof__ (+( + 2 + ))) 0)) == 8))))) 0 : (__typeof__ (0 ? (__typeof__ (0 ? (double *) 0 : (void *) (!((__builtin_classify_type ((__typeof__ (+( + 2 + ))) 0) == 1))))) 0 : (__typeof__ (0 ? (_Complex double *) 0 : (void *) (!((__builtin_classify_type ((__typeof__ (+( + 2 + ))) 0) == 9 && __builtin_classify_type (__real__ ((__typeof__ (+( + 2 + ))) 0)) == 1))))) 0)) 0))) 0)) cpowl ( + 1.0iF + , + 2 + )) : (sizeof (+__real__ ( + 1.0iF + )) == sizeof (double) || sizeof (+__real__ ( + 2 + )) == sizeof (double) || __builtin_classify_type (__real__ ( + 1.0iF + )) != 8 || __builtin_classify_type (__real__ ( + 2 + )) != 8) ? ((__builtin_classify_type (( + 1.0iF + ) + ( + 2 + )) != 9) ? (__typeof ((__typeof__ (*(0 ? (__typeof__ (0 ? (__typeof__ ((__typeof__ (+( + 1.0iF + ))) 0) *) 0 : (void *) (!((__builtin_classify_type (__real__ ((__typeof__ (+( + 1.0iF + ))) 0)) == 8))))) 0 : (__typeof__ (0 ? (__typeof__ (0 ? (double *) 0 : (void *) (!((__builtin_classify_type ((__typeof__ (+( + 1.0iF + ))) 0) == 1))))) 0 : (__typeof__ (0 ? (_Complex double *) 0 : (void *) (!((__builtin_classify_type ((__typeof__ (+( + 1.0iF + ))) 0) == 9 && __builtin_classify_type (__real__ ((__typeof__ (+( + 1.0iF + ))) 0)) == 1))))) 0)) 0))) 0 + (__typeof__ (*(0 ? (__typeof__ (0 ? (__typeof__ ((__typeof__ (+( + 2 + ))) 0) *) 0 : (void *) (!((__builtin_classify_type (__real__ ((__typeof__ (+( + 2 + ))) 0)) == 8))))) 0 : (__typeof__ (0 ? (__typeof__ (0 ? (double *) 0 : (void *) (!((__builtin_classify_type ((__typeof__ (+( + 2 + ))) 0) == 1))))) 0 : (__typeof__ (0 ? (_Complex double *) 0 : (void *) (!((__builtin_classify_type ((__typeof__ (+( + 2 + ))) 0) == 9 && __builtin_classify_type (__real__ ((__typeof__ (+( + 2 + ))) 0)) == 1))))) 0)) 0))) 0)) pow ( + 1.0iF + , + 2 + ) : (__typeof ((__typeof__ (*(0 ? (__typeof__ (0 ? (__typeof__ ((__typeof__ (+( + 1.0iF + ))) 0) *) 0 : (void *) (!((__builtin_classify_type (__real__ ((__typeof__ (+( + 1.0iF + ))) 0)) == 8))))) 0 : (__typeof__ (0 ? (__typeof__ (0 ? (double *) 0 : (void *) (!((__builtin_classify_type ((__typeof__ (+( + 1.0iF + ))) 0) == 1))))) 0 : (__typeof__ (0 ? (_Complex double *) 0 : (void *) (!((__builtin_classify_type ((__typeof__ (+( + 1.0iF + ))) 0) == 9 && __builtin_classify_type (__real__ ((__typeof__ (+( + 1.0iF + ))) 0)) == 1))))) 0)) 0))) 0 + (__typeof__ (*(0 ? (__typeof__ (0 ? (__typeof__ ((__typeof__ (+( + 2 + ))) 0) *) 0 : (void *) (!((__builtin_classify_type (__real__ ((__typeof__ (+( + 2 + ))) 0)) == 8))))) 0 : (__typeof__ (0 ? (__typeof__ (0 ? (double *) 0 : (void *) (!((__builtin_classify_type ((__typeof__ (+( + 2 + ))) 0) == 1))))) 0 : (__typeof__ (0 ? (_Complex double *) 0 : (void *) (!((__builtin_classify_type ((__typeof__ (+( + 2 + ))) 0) == 9 && __builtin_classify_type (__real__ ((__typeof__ (+( + 2 + ))) 0)) == 1))))) 0)) 0))) 0)) cpow ( + 1.0iF + , + 2 + )) : ((__builtin_classify_type (( + 1.0iF + ) + ( + 2 + )) != 9) ? (__typeof ((__typeof__ (*(0 ? (__typeof__ (0 ? (__typeof__ ((__typeof__ (+( + 1.0iF + ))) 0) *) 0 : (void *) (!((__builtin_classify_type (__real__ ((__typeof__ (+( + 1.0iF + ))) 0)) == 8))))) 0 : (__typeof__ (0 ? (__typeof__ (0 ? (double *) 0 : (void *) (!((__builtin_classify_type ((__typeof__ (+( + 1.0iF + ))) 0) == 1))))) 0 : (__typeof__ (0 ? (_Complex double *) 0 : (void *) (!((__builtin_classify_type ((__typeof__ (+( + 1.0iF + ))) 0) == 9 && __builtin_classify_type (__real__ ((__typeof__ (+( + 1.0iF + ))) 0)) == 1))))) 0)) 0))) 0 + (__typeof__ (*(0 ? (__typeof__ (0 ? (__typeof__ ((__typeof__ (+( + 2 + ))) 0) *) 0 : (void *) (!((__builtin_classify_type (__real__ ((__typeof__ (+( + 2 + ))) 0)) == 8))))) 0 : (__typeof__ (0 ? (__typeof__ (0 ? (double *) 0 : (void *) (!((__builtin_classify_type ((__typeof__ (+( + 2 + ))) 0) == 1))))) 0 : (__typeof__ (0 ? (_Complex double *) 0 : (void *) (!((__builtin_classify_type ((__typeof__ (+( + 2 + ))) 0) == 9 && __builtin_classify_type (__real__ ((__typeof__ (+( + 2 + ))) 0)) == 1))))) 0)) 0))) 0)) powf ( + 1.0iF + , + 2 + ) : (__typeof ((__typeof__ (*(0 ? (__typeof__ (0 ? (__typeof__ ((__typeof__ (+( + 1.0iF + ))) 0) *) 0 : (void *) (!((__builtin_classify_type (__real__ ((__typeof__ (+( + 1.0iF + ))) 0)) == 8))))) 0 : (__typeof__ (0 ? (__typeof__ (0 ? (double *) 0 : (void *) (!((__builtin_classify_type ((__typeof__ (+( + 1.0iF + ))) 0) == 1))))) 0 : (__typeof__ (0 ? (_Complex double *) 0 : (void *) (!((__builtin_classify_type ((__typeof__ (+( + 1.0iF + ))) 0) == 9 && __builtin_classify_type (__real__ ((__typeof__ (+( + 1.0iF + ))) 0)) == 1))))) 0)) 0))) 0 + (__typeof__ (*(0 ? (__typeof__ (0 ? (__typeof__ ((__typeof__ (+( + 2 + ))) 0) *) 0 : (void *) (!((__builtin_classify_type (__real__ ((__typeof__ (+( + 2 + ))) 0)) == 8))))) 0 : (__typeof__ (0 ? (__typeof__ (0 ? (double *) 0 : (void *) (!((__builtin_classify_type ((__typeof__ (+( + 2 + ))) 0) == 1))))) 0 : (__typeof__ (0 ? (_Complex double *) 0 : (void *) (!((__builtin_classify_type ((__typeof__ (+( + 2 + ))) 0) == 9 && __builtin_classify_type (__real__ ((__typeof__ (+( + 2 + ))) 0)) == 1))))) 0)) 0))) 0)) cpowf ( + 1.0iF + , + 2 + )))) + ; } From 65bf016573a299f3a331d477693bfa0bdb88264b Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Wed, 15 Jan 2020 17:38:15 +0100 Subject: [PATCH 18/36] Add size and alignment for complex types to CIL machine configuration Requires running ./configure after pulling if it is not a fresh checkout Should mean complex and tgmath work now, more tests needed though. References #8, References #9 --- Makefile.in | 6 +++ src/cil.ml | 11 +++-- src/machdep-ml.c.in | 108 +++++++++++++++++++++++++++++--------------- src/machdepenv.ml | 6 +++ 4 files changed, 91 insertions(+), 40 deletions(-) diff --git a/Makefile.in b/Makefile.in index b68a247c0..f7c2b9061 100644 --- a/Makefile.in +++ b/Makefile.in @@ -167,6 +167,9 @@ $(OBJDIR)/machdep.ml : src/machdep-ml.c configure.ac Makefile.in @echo " sizeof_float: int; (* Size of \"float\" *)" >> $@ @echo " sizeof_double: int; (* Size of \"double\" *)" >> $@ @echo " sizeof_longdouble: int; (* Size of \"long double\" *)" >> $@ + @echo " sizeof_floatcomplex: int; (* Size of \"float _Complex\" *)" >> $@ + @echo " sizeof_doublecomplex: int; (* Size of \"double _Complex\" *)" >> $@ + @echo " sizeof_longdoublecomplex: int; (* Size of \"long double _Complex\" *)" >> $@ @echo " sizeof_void: int; (* Size of \"void\" *)" >> $@ @echo " sizeof_fun: int; (* Size of function *)" >> $@ @echo " size_t: string; (* Type of \"sizeof(T)\" *)" >> $@ @@ -181,6 +184,9 @@ $(OBJDIR)/machdep.ml : src/machdep-ml.c configure.ac Makefile.in @echo " alignof_float: int; (* Alignment of \"float\" *)" >> $@ @echo " alignof_double: int; (* Alignment of \"double\" *)" >> $@ @echo " alignof_longdouble: int; (* Alignment of \"long double\" *)" >> $@ + @echo " alignof_floatcomplex: int; (* Alignment of \"float _Complex\" *)" >> $@ + @echo " alignof_doublecomplex: int; (* Alignment of \"double _Complex\" *)" >> $@ + @echo " alignof_longdoublecomplex: int; (* Alignment of \"long double _Complex\" *)" >> $@ @echo " alignof_str: int; (* Alignment of strings *)" >> $@ @echo " alignof_fun: int; (* Alignment of function *)" >> $@ @echo " alignof_aligned: int; (* Alignment of anything with the \"aligned\" attribute *)" >> $@ diff --git a/src/cil.ml b/src/cil.ml index 1e387d4dc..db6641646 100755 --- a/src/cil.ml +++ b/src/cil.ml @@ -2184,9 +2184,9 @@ let rec alignOf_int t = | TFloat(FFloat, _) -> !M.theMachine.M.alignof_float | TFloat(FDouble, _) -> !M.theMachine.M.alignof_double | TFloat(FLongDouble, _) -> !M.theMachine.M.alignof_longdouble - | TFloat(FComplexFloat, _) -> !M.theMachine.M.alignof_float (* TODO! *) - | TFloat(FComplexDouble, _) -> !M.theMachine.M.alignof_double (* TODO! *) - | TFloat(FComplexLongDouble, _) -> !M.theMachine.M.alignof_longdouble (* TODO! *) + | TFloat(FComplexFloat, _) -> !M.theMachine.M.alignof_floatcomplex + | TFloat(FComplexDouble, _) -> !M.theMachine.M.alignof_doublecomplex + | TFloat(FComplexLongDouble, _) -> !M.theMachine.M.alignof_longdoublecomplex | TNamed (t, _) -> alignOf_int t.ttype | TArray (t, _, _) -> alignOf_int t | TPtr _ | TBuiltin_va_list _ -> !M.theMachine.M.alignof_ptr @@ -2446,7 +2446,10 @@ and bitsSizeOf t = | TInt (ik,_) -> 8 * (bytesSizeOfInt ik) | TFloat(FDouble, _) -> 8 * !M.theMachine.M.sizeof_double | TFloat(FLongDouble, _) -> 8 * !M.theMachine.M.sizeof_longdouble - | TFloat _ -> 8 * !M.theMachine.M.sizeof_float + | TFloat(FFloat, _) -> 8 * !M.theMachine.M.sizeof_float + | TFloat(FComplexDouble, _) -> 8 * !M.theMachine.M.sizeof_doublecomplex + | TFloat(FComplexLongDouble, _) -> 8 * !M.theMachine.M.sizeof_longdoublecomplex + | TFloat(FComplexFloat, _) -> 8 * !M.theMachine.M.sizeof_floatcomplex | TEnum (ei, _) -> bitsSizeOf (TInt(ei.ekind, [])) | TPtr _ -> 8 * !M.theMachine.M.sizeof_ptr | TBuiltin_va_list _ -> 8 * !M.theMachine.M.sizeof_ptr diff --git a/src/machdep-ml.c.in b/src/machdep-ml.c.in index 138399fa9..2fb691d45 100644 --- a/src/machdep-ml.c.in +++ b/src/machdep-ml.c.in @@ -101,8 +101,10 @@ int main(int argc, char **argv) { int env = argc == 2 && !strcmp(argv[1], "--env"); int alignof_short, alignof_int, alignof_long, alignof_ptr, alignof_enum, - alignof_float, alignof_double, alignof_longdouble, sizeof_fun, - alignof_fun, alignof_str, alignof_aligned, alignof_longlong, + alignof_float, alignof_double, alignof_longdouble, + alignof_floatcomplex, alignof_doublecomplex, alignof_longdoublecomplex, + sizeof_fun, + alignof_fun, alignof_str, alignof_aligned, alignof_longlong, little_endian, char_is_unsigned, alignof_bool; // The alignment of a short @@ -195,6 +197,33 @@ int main(int argc, char **argv) alignof_longdouble = (intptr_t)(&((struct s1*)0)->ld); } + // The alignment of a float complex + { + struct floatstruct { + char c; + float _Complex f; + }; + alignof_floatcomplex = (intptr_t)(&((struct floatstruct*)0)->f); + } + + // The alignment of double complex + { + struct s1 { + char c; + double _Complex d; + }; + alignof_doublecomplex = (intptr_t)(&((struct s1*)0)->d); + } + + // The alignment of long double complex + { + struct s1 { + char c; + long double _Complex ld; + }; + alignof_longdoublecomplex = (intptr_t)(&((struct s1*)0)->ld); + } + alignof_str = __alignof("a string"); alignof_fun = __alignof(main); @@ -231,7 +260,7 @@ int main(int argc, char **argv) { fprintf(stderr, "Generating CIL_MACHINE machine dependency information string (for CIL)\n"); printf("short=%d,%d int=%d,%d long=%d,%d long_long=%d,%d pointer=%d,%d " - "alignof_enum=%d float=%d,%d double=%d,%d long_double=%d,%d void=%d " + "alignof_enum=%d float=%d,%d double=%d,%d long_double=%d,%d float_complex=%d,%d double_complex=%d,%d long_double_complex=%d,%d void=%d " "bool=%d,%d fun=%d,%d alignof_string=%d max_alignment=%d size_t=%s " "wchar_t=%s char_signed=%s const_string_literals=%s " "big_endian=%s __thread_is_keyword=%s __builtin_va_list=%s " @@ -240,7 +269,8 @@ int main(int argc, char **argv) (int)sizeof(long), alignof_long, (int)sizeof(long long), alignof_longlong, (int)sizeof(int *), alignof_ptr, alignof_enum, (int)sizeof(float), alignof_float, (int)sizeof(double), alignof_double, - (int)sizeof(long double), alignof_longdouble, (int)sizeof(void), + (int)sizeof(long double), alignof_longdouble, (int)sizeof(float _Complex), alignof_floatcomplex, (int)sizeof(double _Complex), alignof_doublecomplex, + (int)sizeof(long double _Complex), alignof_longdoublecomplex, (int)sizeof(void), (int)sizeof(bool), alignof_bool, sizeof_fun, alignof_fun, alignof_str, alignof_aligned, underscore(TYPE_SIZE_T), underscore(TYPE_WCHAR_T), @@ -258,38 +288,44 @@ int main(int argc, char **argv) printf("\t version = \"%s\";\n", VERSION); // Size of certain types - printf("\t sizeof_short = %d;\n", (int)sizeof(short)); - printf("\t sizeof_int = %d;\n", (int)sizeof(int)); - printf("\t sizeof_bool = %d;\n", (int)sizeof(bool)); - printf("\t sizeof_long = %d;\n", (int)sizeof(long)); - printf("\t sizeof_longlong = %d;\n", (int)sizeof(LONGLONG)); - printf("\t sizeof_ptr = %d;\n", (int)sizeof(int *)); - printf("\t sizeof_float = %d;\n", (int)sizeof(float)); - printf("\t sizeof_double = %d;\n", (int)sizeof(double)); - printf("\t sizeof_longdouble = %d;\n", (int)sizeof(long double)); - printf("\t sizeof_void = %d;\n", (int)sizeof(void)); - printf("\t sizeof_fun = %d;\n", (int)sizeof_fun); - printf("\t size_t = \"%s\";\n", TYPE_SIZE_T); - printf("\t wchar_t = \"%s\";\n", TYPE_WCHAR_T); - printf("\t alignof_short = %d;\n", alignof_short); - printf("\t alignof_int = %d;\n", alignof_int); - printf("\t alignof_bool = %d;\n", alignof_bool); - printf("\t alignof_long = %d;\n", alignof_long); - printf("\t alignof_longlong = %d;\n", alignof_longlong); - printf("\t alignof_ptr = %d;\n", alignof_ptr); - printf("\t alignof_enum = %d;\n", alignof_enum); - printf("\t alignof_float = %d;\n", alignof_float); - printf("\t alignof_double = %d;\n", alignof_double); - printf("\t alignof_longdouble = %d;\n", alignof_longdouble); - printf("\t alignof_str = %d;\n", alignof_str); - printf("\t alignof_fun = %d;\n", alignof_fun); - printf("\t alignof_aligned = %d;\n", alignof_aligned); - printf("\t char_is_unsigned = %s;\n", char_is_unsigned ? "true" : "false"); - printf("\t const_string_literals = %s;\n", CONST_STRING_LITERALS); - printf("\t underscore_name = %s;\n", UNDERSCORE_NAME); - printf("\t __builtin_va_list = %s;\n", HAVE_BUILTIN_VA_LIST); - printf("\t __thread_is_keyword = %s;\n", THREAD_IS_KEYWORD); - printf("\t little_endian = %s;\n", little_endian ? "true" : "false"); + printf("\t sizeof_short = %d;\n", (int)sizeof(short)); + printf("\t sizeof_int = %d;\n", (int)sizeof(int)); + printf("\t sizeof_bool = %d;\n", (int)sizeof(bool)); + printf("\t sizeof_long = %d;\n", (int)sizeof(long)); + printf("\t sizeof_longlong = %d;\n", (int)sizeof(LONGLONG)); + printf("\t sizeof_ptr = %d;\n", (int)sizeof(int *)); + printf("\t sizeof_float = %d;\n", (int)sizeof(float)); + printf("\t sizeof_double = %d;\n", (int)sizeof(double)); + printf("\t sizeof_longdouble = %d;\n", (int)sizeof(long double)); + printf("\t sizeof_floatcomplex = %d;\n", (int)sizeof(float _Complex)); + printf("\t sizeof_doublecomplex = %d;\n", (int)sizeof(double _Complex)); + printf("\t sizeof_longdoublecomplex = %d;\n", (int)sizeof(long double _Complex)); + printf("\t sizeof_void = %d;\n", (int)sizeof(void)); + printf("\t sizeof_fun = %d;\n", (int)sizeof_fun); + printf("\t size_t = \"%s\";\n", TYPE_SIZE_T); + printf("\t wchar_t = \"%s\";\n", TYPE_WCHAR_T); + printf("\t alignof_short = %d;\n", alignof_short); + printf("\t alignof_int = %d;\n", alignof_int); + printf("\t alignof_bool = %d;\n", alignof_bool); + printf("\t alignof_long = %d;\n", alignof_long); + printf("\t alignof_longlong = %d;\n", alignof_longlong); + printf("\t alignof_ptr = %d;\n", alignof_ptr); + printf("\t alignof_enum = %d;\n", alignof_enum); + printf("\t alignof_float = %d;\n", alignof_float); + printf("\t alignof_double = %d;\n", alignof_double); + printf("\t alignof_longdouble = %d;\n", alignof_longdouble); + printf("\t alignof_floatcomplex = %d;\n", alignof_floatcomplex); + printf("\t alignof_doublecomplex = %d;\n", alignof_doublecomplex); + printf("\t alignof_longdoublecomplex = %d;\n", alignof_longdoublecomplex); + printf("\t alignof_str = %d;\n", alignof_str); + printf("\t alignof_fun = %d;\n", alignof_fun); + printf("\t alignof_aligned = %d;\n", alignof_aligned); + printf("\t char_is_unsigned = %s;\n", char_is_unsigned ? "true" : "false"); + printf("\t const_string_literals = %s;\n", CONST_STRING_LITERALS); + printf("\t underscore_name = %s;\n", UNDERSCORE_NAME); + printf("\t __builtin_va_list = %s;\n", HAVE_BUILTIN_VA_LIST); + printf("\t __thread_is_keyword = %s;\n", THREAD_IS_KEYWORD); + printf("\t little_endian = %s;\n", little_endian ? "true" : "false"); } return 0; } diff --git a/src/machdepenv.ml b/src/machdepenv.ml index d48767a8f..2707946b7 100644 --- a/src/machdepenv.ml +++ b/src/machdepenv.ml @@ -71,10 +71,16 @@ let modelParse (s:string) : mach = alignof_enum = getInt entries "alignof_enum"; sizeof_float = getSizeof entries "float"; alignof_float = getAlignof entries "float"; + sizeof_floatcomplex = getSizeof entries "float_complex"; + alignof_floatcomplex = getAlignof entries "float_complex"; sizeof_double = getSizeof entries "double"; alignof_double = getAlignof entries "double"; + sizeof_doublecomplex = getSizeof entries "double_complex"; + alignof_doublecomplex = getAlignof entries "double_complex"; sizeof_longdouble = getSizeof entries "long_double"; alignof_longdouble = getAlignof entries "long_double"; + sizeof_longdoublecomplex = getSizeof entries "long_double_complex"; + alignof_longdoublecomplex = getAlignof entries "long_double_complex"; sizeof_void = getSizeof entries "void"; sizeof_fun = getSizeof entries "fun"; alignof_fun = getAlignof entries "fun"; From 1d712974a20ad671239825bf4edd0128754fdc1f Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Thu, 16 Jan 2020 09:33:50 +0100 Subject: [PATCH 19/36] Fix arithmetic conversion to work for complex. References #8, References #9 --- src/frontc/cabs2cil.ml | 31 +++++++++++++++++++------------ test/small1/c99-complex.c | 6 +++++- 2 files changed, 24 insertions(+), 13 deletions(-) diff --git a/src/frontc/cabs2cil.ml b/src/frontc/cabs2cil.ml index 9ab4eb9b1..90f420087 100644 --- a/src/frontc/cabs2cil.ml +++ b/src/frontc/cabs2cil.ml @@ -1254,19 +1254,26 @@ let defaultArgumentPromotion (t : typ) : typ = (* c.f. ISO 6.5.2.2:6 *) let arithmeticConversion (* c.f. ISO 6.3.1.8 *) (t1: typ) (t2: typ) : typ = + let resultingFType fkind1 t1 fkind2 t2 = + (* t1 and t2 are the original types before unrollType, so TNamed is preserved if possible *) + let isComplex f = f = FComplexFloat || f = FComplexDouble || f = FComplexLongDouble in + match fkind1, fkind2 with + | FComplexLongDouble, _ -> t1 + | _, FComplexLongDouble -> t2 + | FLongDouble, other -> if isComplex other then TFloat(FComplexLongDouble, []) else t1 + | other, FLongDouble -> if isComplex other then TFloat(FComplexLongDouble, []) else t2 + | FComplexDouble, other -> t1 + | other, FComplexDouble -> t2 + | FDouble, other -> if isComplex other then TFloat(FComplexDouble, []) else t1 + | other, FDouble -> if isComplex other then TFloat(FComplexDouble, []) else t2 + | FComplexFloat, other -> t1 + | other, FComplexFloat -> t2 + | FFloat, FFloat -> t1 + in match unrollType t1, unrollType t2 with - TFloat(FLongDouble, _), _ -> t1 - | TFloat(FComplexLongDouble, _), _ -> t1 - | _, TFloat(FLongDouble, _) -> t2 - | _, TFloat(FComplexLongDouble, _) -> t2 - | TFloat(FDouble, _), _ -> t1 - | TFloat(FComplexDouble, _), _ -> t1 - | _, TFloat (FDouble, _) -> t2 - | _, TFloat (FComplexDouble, _) -> t2 - | TFloat(FFloat, _), _ -> t1 - | TFloat(FComplexFloat, _), _ -> t1 - | _, TFloat (FFloat, _) -> t2 - | _, TFloat (FComplexFloat, _) -> t2 + | TFloat(fkind1, _), TFloat(fkind2, _) -> resultingFType fkind1 t1 fkind2 t2 + | TFloat(_, _), _ -> t1 + | _, TFloat(_, _) -> t2 | _, _ -> begin let t1' = integralPromotion t1 in let t2' = integralPromotion t2 in diff --git a/test/small1/c99-complex.c b/test/small1/c99-complex.c index 9da6b0e77..ac8123e25 100644 --- a/test/small1/c99-complex.c +++ b/test/small1/c99-complex.c @@ -22,10 +22,14 @@ int main(void) { double complex x1 = 1.0iF + 0.5; + if(sizeof(double complex) != sizeof(1.0iF + 0.5)) { + E(1); + } + double d = creal(x1); if(d != 0.5) - E(1); + E(2); double complex z1 = 1.0iF + 1; printf("I * I = %.1f%+.1fi\n", creal(z1), cimag(z1)); From 7e85e55aa89f6652e18e7c3780f1686d0414896f Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Thu, 16 Jan 2020 10:58:50 +0100 Subject: [PATCH 20/36] Ensure complex have the correct fkind rather than having the "complex" attribute And also check this in check.ml --- src/check.ml | 5 ++++- src/cil.ml | 9 +++++++++ src/cil.mli | 3 +++ src/frontc/cabs2cil.ml | 27 ++++++++++++++++----------- 4 files changed, 32 insertions(+), 12 deletions(-) diff --git a/src/check.ml b/src/check.ml index 050eecd4f..12eba9005 100644 --- a/src/check.ml +++ b/src/check.ml @@ -237,7 +237,10 @@ let rec checkType (t: typ) (ctx: ctxType) = match t with (TVoid a | TBuiltin_va_list a) -> checkAttributes a | TInt (ik, a) -> checkAttributes a - | TFloat (_, a) -> checkAttributes a + | TFloat (_, a) -> + checkAttributes a; + if hasAttribute "complex" a then + E.s (E.bug "float type has attribute complex, this should never be the case as there are fkinds for this"); | TPtr (t, a) -> checkAttributes a; checkType t CTPtr | TNamed (ti, a) -> diff --git a/src/cil.ml b/src/cil.ml index db6641646..7009d66fb 100755 --- a/src/cil.ml +++ b/src/cil.ml @@ -1614,6 +1614,15 @@ let typeOfReal t = TFloat (newfkind fkind, newattrs) | _ -> E.s (E.bug "unexpected non-numerical type for argument to __real__") +(** for an fkind, return the corresponding complex fkind *) +let getComplexFkind = function + | FFloat -> FComplexFloat + | FDouble -> FComplexDouble + | FLongDouble -> FComplexLongDouble + | FComplexFloat -> FComplexFloat + | FComplexDouble -> FComplexDouble + | FComplexLongDouble -> FComplexLongDouble + let var vi : lval = (Var vi, NoOffset) (* let assign vi e = Instrs(Set (var vi, e), lu) *) diff --git a/src/cil.mli b/src/cil.mli index c332b220c..b7a1aa7ee 100644 --- a/src/cil.mli +++ b/src/cil.mli @@ -1327,6 +1327,9 @@ val isVoidPtrType: typ -> bool (** for numerical __complex types return type of corresponding real part *) val typeOfReal: typ -> typ +(** for an fkind, return the corresponding complex fkind *) +val getComplexFkind: fkind -> fkind + (** int *) val intType: typ diff --git a/src/frontc/cabs2cil.ml b/src/frontc/cabs2cil.ml index 90f420087..829d9796f 100644 --- a/src/frontc/cabs2cil.ml +++ b/src/frontc/cabs2cil.ml @@ -1496,9 +1496,9 @@ let cabsTypeAddAttributes a0 t = t | _ -> (* anything else: add a0 to existing attributes *) - let add (a: attributes) = cabsAddAttributes a0 a in + let addA0To (a: attributes) = cabsAddAttributes a0 a in match t with - TVoid a -> TVoid (add a) + TVoid a -> TVoid (addA0To a) | TInt (ik, a) -> (* Here we have to watch for the mode attribute *) (* sm: This stuff is to handle a GCC extension where you can request integers*) @@ -1512,7 +1512,7 @@ let cabsTypeAddAttributes a0 t = (* A consequence of this handling is that we throw away the mode *) (* attribute, which we used to go out of our way to avoid printing anyway.*) (* DG: Use machine model to pick correct type *) - let ik', a0' = + let ik', a0' = begin (* Go over the list of new attributes and come back with a * filtered list and a new integer kind *) List.fold_left @@ -1544,17 +1544,22 @@ let cabsTypeAddAttributes a0 t = | _ -> (ik', a0one :: a0')) (ik, []) a0 + end in TInt (ik', cabsAddAttributes a0' a) - | TFloat (fk, a) -> TFloat (fk, add a) - | TEnum (enum, a) -> TEnum (enum, add a) - | TPtr (t, a) -> TPtr (t, add a) - | TArray (t, l, a) -> TArray (t, l, add a) - | TFun (t, args, isva, a) -> TFun(t, args, isva, add a) - | TComp (comp, a) -> TComp (comp, add a) - | TNamed (t, a) -> TNamed (t, add a) - | TBuiltin_va_list a -> TBuiltin_va_list (add a) + | TFloat (fk, a) -> + if Cil.hasAttribute "complex" a0 then + TFloat (Cil.getComplexFkind fk, cabsAddAttributes (Cil.dropAttribute "complex" a0) a) + else + TFloat (fk, addA0To a) + | TEnum (enum, a) -> TEnum (enum, addA0To a) + | TPtr (t, a) -> TPtr (t, addA0To a) + | TArray (t, l, a) -> TArray (t, l, addA0To a) + | TFun (t, args, isva, a) -> TFun(t, args, isva, addA0To a) + | TComp (comp, a) -> TComp (comp, addA0To a) + | TNamed (t, a) -> TNamed (t, addA0To a) + | TBuiltin_va_list a -> TBuiltin_va_list (addA0To a) end From 673fd859fee657003cb790b4b86a4694ee166872 Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Thu, 16 Jan 2020 11:26:55 +0100 Subject: [PATCH 21/36] Be more lenient when accepting complex float constants. iF can also be written Fi i is the same as Di References #8, References #9 --- src/frontc/cabs2cil.ml | 10 +++++----- src/frontc/clexer.mll | 2 +- test/small1/c99-complex.c | 2 ++ test/small1/c99-tgmath.c | 7 +++++++ 4 files changed, 15 insertions(+), 6 deletions(-) diff --git a/src/frontc/cabs2cil.ml b/src/frontc/cabs2cil.ml index 829d9796f..c18982873 100644 --- a/src/frontc/cabs2cil.ml +++ b/src/frontc/cabs2cil.ml @@ -3583,14 +3583,14 @@ and doExp (asconst: bool) (* This expression is used as a constant *) (* Maybe it ends in U or UL. Strip those *) let l = String.length str in let baseint, kind = - if hasSuffix str "iL" then + if hasSuffix str "iL" || hasSuffix str "Li" then String.sub str 0 (l - 2), FComplexLongDouble - else if hasSuffix str "iF" then + else if hasSuffix str "iF" || hasSuffix str "Fi" then String.sub str 0 (l - 2), FComplexFloat - else if hasSuffix str "iD" then + else if hasSuffix str "iD" || hasSuffix str "Di" then String.sub str 0 (l - 2), FComplexDouble - else - str, FComplexDouble (* this is not ok *) + else (* A.CONST_COMPLEX always has the suffix i *) + String.sub str 0 (l - 1), FComplexDouble in if kind = FLongDouble then (* We only have 64-bit values in Ocaml *) diff --git a/src/frontc/clexer.mll b/src/frontc/clexer.mll index 6985b6da1..8a772e372 100644 --- a/src/frontc/clexer.mll +++ b/src/frontc/clexer.mll @@ -438,7 +438,7 @@ let hexfloat = hexprefix hexfraction binexponent let floatsuffix = ['f' 'F' 'l' 'L'] let floatnum = (decfloat | hexfloat) floatsuffix? -let complexnum = (decfloat | hexfloat) ['i' 'I'] floatsuffix +let complexnum = (decfloat | hexfloat) ((['i' 'I'] floatsuffix) | (floatsuffix? ['i' 'I'])) let ident = (letter|'_'|'$')(letter|decdigit|'_'|'$')* diff --git a/test/small1/c99-complex.c b/test/small1/c99-complex.c index ac8123e25..fdc6a7071 100644 --- a/test/small1/c99-complex.c +++ b/test/small1/c99-complex.c @@ -20,7 +20,9 @@ void forlong() { int main(void) { + double complex x0 = 1.0i + 17; double complex x1 = 1.0iF + 0.5; + double complex x00 = 1.0Fi + 0.5; if(sizeof(double complex) != sizeof(1.0iF + 0.5)) { E(1); diff --git a/test/small1/c99-tgmath.c b/test/small1/c99-tgmath.c index ff2b003d2..5597fbbf8 100644 --- a/test/small1/c99-tgmath.c +++ b/test/small1/c99-tgmath.c @@ -1,5 +1,6 @@ #include #include +#include #include "testharness.h" int main(void) @@ -8,6 +9,12 @@ int main(void) double d = fabs(1.0); long l = fabs(1.0l); + float _Complex fc = 3.25f + 0.1if; + float f2 = fabs(fc); + + double _Complex fcd = 3.25 + 0.1i; + double f2d = fabs(fcd); + if(f != 1.0f) E(1); From 5c39b0e1bdf4dd737978a69ee568fe8e5d7dd71b Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Thu, 16 Jan 2020 12:51:58 +0100 Subject: [PATCH 22/36] Cleanup --- src/cil.ml | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/cil.ml b/src/cil.ml index 7009d66fb..c14a95b84 100755 --- a/src/cil.ml +++ b/src/cil.ml @@ -1610,8 +1610,7 @@ let typeOfReal t = | FComplexDouble -> FDouble | FComplexLongDouble -> FLongDouble in - let newattrs = dropAttribute "complex" attrs in - TFloat (newfkind fkind, newattrs) + TFloat (newfkind fkind, attrs) | _ -> E.s (E.bug "unexpected non-numerical type for argument to __real__") (** for an fkind, return the corresponding complex fkind *) @@ -3393,10 +3392,6 @@ class defaultCilPrinterClass : cilPrinter = object (self) (* variable declaration *) method pVDecl () (v:varinfo) = - (* These were treated as if they were functions but they are not *) - (* if v.vname = "__real__" || v.vname = "__imag__" then - nil - else *) let stom, rest = separateStorageModifiers v.vattr in (* First the storage modifiers *) text (if v.vinline then "__inline " else "") From 1cde4765bcd76ceefffbe22bf6d097c8a9a7144a Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Thu, 16 Jan 2020 13:18:46 +0100 Subject: [PATCH 23/36] Add support for __imag__ References #8, References #9 --- src/check.ml | 7 ++++--- src/cil.ml | 8 ++++---- src/cil.mli | 4 ++-- src/frontc/cabs2cil.ml | 7 +++++-- test/small1/c99-complex.c | 6 ++++++ 5 files changed, 21 insertions(+), 11 deletions(-) diff --git a/src/check.ml b/src/check.ml index 12eba9005..22049f443 100644 --- a/src/check.ml +++ b/src/check.ml @@ -500,9 +500,10 @@ and checkExp (isconst: bool) (e: exp) : typ = | Real e -> let te = checkExp isconst e in - typeOfReal te - | Imag e -> E.s (E.bug "unimplemented") - + typeOfRealAndImagComponents te + | Imag e -> + let te = checkExp isconst e in + typeOfRealAndImagComponents te | AlignOf(t) -> begin (* Sizeof cannot be applied to certain types *) checkType t CTSizeof; diff --git a/src/cil.ml b/src/cil.ml index c14a95b84..59180456a 100755 --- a/src/cil.ml +++ b/src/cil.ml @@ -1597,8 +1597,8 @@ let isVoidPtrType t = TPtr(tau,_) when isVoidType tau -> true | _ -> false -(* get the typ of __real__(e) for e of typ t*) -let typeOfReal t = +(* get the typ of __real__(e) or __imag__(e) for e of typ t*) +let typeOfRealAndImagComponents t = match unrollType t with | TInt _ -> t | TFloat (fkind, attrs) -> @@ -1920,8 +1920,8 @@ let rec typeOf (e: exp) : typ = | Const(CReal (_, fk, _)) -> TFloat(fk, []) | Const(CEnum(tag, _, ei)) -> typeOf tag - | Real e -> typeOfReal @@ typeOf e - | Imag e -> E.s (E.bug "unsupported") + | Real e -> typeOfRealAndImagComponents @@ typeOf e + | Imag e -> typeOfRealAndImagComponents @@ typeOf e | Lval(lv) -> typeOfLval lv | SizeOf _ | SizeOfE _ | SizeOfStr _ -> !typeOfSizeOf | AlignOf _ | AlignOfE _ -> !typeOfSizeOf diff --git a/src/cil.mli b/src/cil.mli index b7a1aa7ee..8e453049b 100644 --- a/src/cil.mli +++ b/src/cil.mli @@ -1324,8 +1324,8 @@ val isVoidType: typ -> bool (** is the given type "void *"? *) val isVoidPtrType: typ -> bool -(** for numerical __complex types return type of corresponding real part *) -val typeOfReal: typ -> typ +(** for numerical __complex types return type of corresponding real part and imaginary parts *) +val typeOfRealAndImagComponents: typ -> typ (** for an fkind, return the corresponding complex fkind *) val getComplexFkind: fkind -> fkind diff --git a/src/frontc/cabs2cil.ml b/src/frontc/cabs2cil.ml index c18982873..de36604de 100644 --- a/src/frontc/cabs2cil.ml +++ b/src/frontc/cabs2cil.ml @@ -3658,8 +3658,11 @@ and doExp (asconst: bool) (* This expression is used as a constant *) | A.REAL e -> let (se, e', t) = doExp false e (AExp None) in let real = Real e' in - finishExp se real (typeOfReal t) - | A.IMAG e -> E.s (bug "cabs2cil: unsupported") + finishExp se real (typeOfRealAndImagComponents t) + | A.IMAG e -> + let (se, e', t) = doExp false e (AExp None) in + let imag = Imag e' in + finishExp se imag (typeOfRealAndImagComponents t) | A.CLASSIFYTYPE e -> let classify_type t = match unrollTypeDeep t with (* See gcc/typeclass.h *) diff --git a/test/small1/c99-complex.c b/test/small1/c99-complex.c index fdc6a7071..85ae7f4e4 100644 --- a/test/small1/c99-complex.c +++ b/test/small1/c99-complex.c @@ -29,10 +29,16 @@ int main(void) } double d = creal(x1); + double i = cimag(x1); + + double j = __imag__(1.0if); if(d != 0.5) E(2); + if(i != 1.0 || j != 1.0) + E(3); + double complex z1 = 1.0iF + 1; printf("I * I = %.1f%+.1fi\n", creal(z1), cimag(z1)); From 691e41174d698c921ea7451d3270c341ce6684aa Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Thu, 16 Jan 2020 14:36:02 +0100 Subject: [PATCH 24/36] Skip failing tests for universal character names and inline --- test/testcil.pl | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/testcil.pl b/test/testcil.pl index 20289dc4a..3af1030de 100644 --- a/test/testcil.pl +++ b/test/testcil.pl @@ -726,8 +726,10 @@ sub addToGroup { addTest("testrunc99/c99-struct"); addTest("testrunc99/c99-complex"); addTest("testrunc99/c99-universal-character-names"); +addBadComment("testrunc99/c99-universal-character-names", "Universal character names are not yet supported"); addTest("testrunc99/c99-tgmath"); -addTest("combinec99inline "); +addTest("combinec99inline"); +addBadComment("combinec99inline", "C99 inline semantic not fully supported."); # ---------------- c-torture ------------- From 252a5970b6d55cc78bd56af0235d279f7bd2c332 Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Fri, 17 Jan 2020 10:42:13 +0100 Subject: [PATCH 25/36] Add comments about what c99Mode does --- src/cil.ml | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/src/cil.ml b/src/cil.ml index 59180456a..5d9c58c67 100755 --- a/src/cil.ml +++ b/src/cil.ml @@ -62,8 +62,14 @@ let cilVersionRevision = Cilversion.cilVersionRev let msvcMode = ref false (* Whether the pretty printer should * print output for the MS VC * compiler. Default is GCC *) -let c99Mode = ref true (* True to handle ISO C 99 vs 90 changes. (* TODO: This should be exposed *) - So far only affects integer parsing. *) +let c99Mode = ref true (* True to handle ISO C 99 vs 90 changes. + c99mode only affects parsing of decimal integer constants without suffix + a) on machines where long and long long do not have the same size + (e.g. 32 Bit machines, 64 Bit Windows, not 64 Bit MacOS or (most? all?) 64 Bit Linux): + giving constants that are bigger than max long type long long in c99mode vs. unsigned long + if c99mode is off. + b) for constants bigger than long long producing a "Unimplemented: Cannot represent the integer" + warning in C99 mode vs. unsigned long long if c99mode is off. *) (* Set this to true to get old-style handling of gcc's extern inline C extension: old-style: the extern inline definition is used until the actual definition is @@ -289,12 +295,12 @@ and ikind = (** Various kinds of floating-point numbers*) and fkind = - FFloat (** [float] *) - | FDouble (** [double] *) - | FLongDouble (** [long double] *) - | FComplexFloat - | FComplexDouble - | FComplexLongDouble + FFloat (** [float] *) + | FDouble (** [double] *) + | FLongDouble (** [long double] *) + | FComplexFloat (** [float _Complex] *) + | FComplexDouble (** [double _Complex] *) + | FComplexLongDouble (** [long double _Complex]*) (** An attribute has a name and some optional parameters *) and attribute = Attr of string * attrparam list @@ -2840,6 +2846,13 @@ let parseInt (str: string) : exp = 0, if octalhex then [IInt; IUInt; ILong; IULong; ILongLong; IULongLong] else if not !c99Mode then [ IInt; ILong; IULong; ILongLong; IULongLong] else [IInt; ILong; ILongLong] + (* c99mode only affects parsing of decimal integer constants without suffix + a) on machines where long and long long do not have the same size + (e.g. 32 Bit machines, 64 Bit Windows, not 64 Bit MacOS or (most? all?) 64 Bit Linux: + giving constants that are bigger than max long type long long in c99mode vs. unsigned long + if c99mode is off. + b) for constants bigger than long long producing a "Unimplemented: Cannot represent the integer" + warning in C99 mode vs. unsigned long long if c99mode is off. *) in (* Convert to integer. To prevent overflow we do the arithmetic on * cilints. We work only with positive integers since the lexer From 4089860c24c1e01d278d3728b2c2634b952a15b7 Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Fri, 17 Jan 2020 11:08:46 +0100 Subject: [PATCH 26/36] Add comments for fkind also to cil.mli --- src/cil.mli | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/cil.mli b/src/cil.mli index 8e453049b..800d72b0f 100644 --- a/src/cil.mli +++ b/src/cil.mli @@ -290,12 +290,12 @@ and ikind = (** Various kinds of floating-point numbers*) and fkind = - FFloat (** [float] *) - | FDouble (** [double] *) - | FLongDouble (** [long double] *) - | FComplexFloat - | FComplexDouble - | FComplexLongDouble + FFloat (** [float] *) + | FDouble (** [double] *) + | FLongDouble (** [long double] *) + | FComplexFloat (** [float _Complex] *) + | FComplexDouble (** [double _Complex] *) + | FComplexLongDouble (** [long double _Complex]*) (** {b Attributes.} *) From ad7f4975596633cfb3aa66655b3284484a79fdf3 Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Tue, 21 Jan 2020 11:18:07 +0100 Subject: [PATCH 27/36] Try setting CC to gcc-9 gcc-8 etc instead of gcc on MacOS gcc is an alias for clang by default, causing tests that rely on gcc specifics to fail --- configure | 410 +++++++++++++++------------------------------------ configure.ac | 17 ++- 2 files changed, 138 insertions(+), 289 deletions(-) diff --git a/configure b/configure index 2560ede45..d9849273a 100755 --- a/configure +++ b/configure @@ -659,14 +659,6 @@ target_os target_vendor target_cpu target -host_os -host_vendor -host_cpu -host -build_os -build_vendor -build_cpu -build INSTALL_DATA INSTALL_SCRIPT INSTALL_PROGRAM @@ -677,6 +669,14 @@ CPPFLAGS LDFLAGS CFLAGS CC +host_os +host_vendor +host_cpu +host +build_os +build_vendor +build_cpu +build target_alias host_alias build_alias @@ -696,6 +696,7 @@ infodir docdir oldincludedir includedir +runstatedir localstatedir sharedstatedir sysconfdir @@ -766,6 +767,7 @@ datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' +runstatedir='${localstatedir}/run' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE}' @@ -1018,6 +1020,15 @@ do | -silent | --silent | --silen | --sile | --sil) silent=yes ;; + -runstatedir | --runstatedir | --runstatedi | --runstated \ + | --runstate | --runstat | --runsta | --runst | --runs \ + | --run | --ru | --r) + ac_prev=runstatedir ;; + -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \ + | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \ + | --run=* | --ru=* | --r=*) + runstatedir=$ac_optarg ;; + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ @@ -1155,7 +1166,7 @@ fi for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ - libdir localedir mandir + libdir localedir mandir runstatedir do eval ac_val=\$$ac_var # Remove trailing slashes. @@ -1308,6 +1319,7 @@ Fine tuning of the installation directories: --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] @@ -2206,203 +2218,126 @@ fi # for @CC@ in output files; you have to do this even if you don't # care about @CC@, because system feature tests later on in # the ./configure script will expect $CC to be set right -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu -if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. -set dummy ${ac_tool_prefix}gcc; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_CC+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$CC"; then - ac_cv_prog_CC="$CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_CC="${ac_tool_prefix}gcc" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 + +# AC_CANONICAL_HOST is needed to access the 'host_os' variable +ac_aux_dir= +for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do + if test -f "$ac_dir/install-sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f "$ac_dir/install.sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + elif test -f "$ac_dir/shtool"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/shtool install -c" + break fi done - done -IFS=$as_save_IFS - -fi -fi -CC=$ac_cv_prog_CC -if test -n "$CC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 -$as_echo "$CC" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } +if test -z "$ac_aux_dir"; then + as_fn_error $? "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5 fi +# These three variables are undocumented and unsupported, +# and are intended to be withdrawn in a future Autoconf release. +# They can cause serious problems if a builder's source tree is in a directory +# whose full name contains unusual characters. +ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. +ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. +ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. -fi -if test -z "$ac_cv_prog_CC"; then - ac_ct_CC=$CC - # Extract the first word of "gcc", so it can be a program name with args. -set dummy gcc; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_ac_ct_CC+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$ac_ct_CC"; then - ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_ac_ct_CC="gcc" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -ac_ct_CC=$ac_cv_prog_ac_ct_CC -if test -n "$ac_ct_CC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 -$as_echo "$ac_ct_CC" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - if test "x$ac_ct_CC" = x; then - CC="" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} -ac_tool_warned=yes ;; -esac - CC=$ac_ct_CC - fi -else - CC="$ac_cv_prog_CC" -fi +# Make sure we can run config.sub. +$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || + as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5 -if test -z "$CC"; then - if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. -set dummy ${ac_tool_prefix}cc; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_CC+:} false; then : +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5 +$as_echo_n "checking build system type... " >&6; } +if ${ac_cv_build+:} false; then : $as_echo_n "(cached) " >&6 else - if test -n "$CC"; then - ac_cv_prog_CC="$CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_CC="${ac_tool_prefix}cc" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS + ac_build_alias=$build_alias +test "x$ac_build_alias" = x && + ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"` +test "x$ac_build_alias" = x && + as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5 +ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` || + as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5 fi -fi -CC=$ac_cv_prog_CC -if test -n "$CC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 -$as_echo "$CC" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5 +$as_echo "$ac_cv_build" >&6; } +case $ac_cv_build in +*-*-*) ;; +*) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;; +esac +build=$ac_cv_build +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_build +shift +build_cpu=$1 +build_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +build_os=$* +IFS=$ac_save_IFS +case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac - fi -fi -if test -z "$CC"; then - # Extract the first word of "cc", so it can be a program name with args. -set dummy cc; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_CC+:} false; then : +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5 +$as_echo_n "checking host system type... " >&6; } +if ${ac_cv_host+:} false; then : $as_echo_n "(cached) " >&6 else - if test -n "$CC"; then - ac_cv_prog_CC="$CC" # Let the user override the test. + if test "x$host_alias" = x; then + ac_cv_host=$ac_cv_build else - ac_prog_rejected=no -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then - ac_prog_rejected=yes - continue - fi - ac_cv_prog_CC="cc" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -if test $ac_prog_rejected = yes; then - # We found a bogon in the path, so make sure we never use it. - set dummy $ac_cv_prog_CC - shift - if test $# != 0; then - # We chose a different compiler from the bogus one. - # However, it has the same basename, so the bogon will be chosen - # first if we set CC to just the basename; use the full file name. - shift - ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" - fi -fi -fi + ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` || + as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5 fi -CC=$ac_cv_prog_CC -if test -n "$CC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 -$as_echo "$CC" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } + fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5 +$as_echo "$ac_cv_host" >&6; } +case $ac_cv_host in +*-*-*) ;; +*) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;; +esac +host=$ac_cv_host +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_host +shift +host_cpu=$1 +host_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +host_os=$* +IFS=$ac_save_IFS +case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac -fi -if test -z "$CC"; then - if test -n "$ac_tool_prefix"; then - for ac_prog in cl.exe + +# Detect the target system +case "${host_os}" in + darwin*) + list_of_compilers="gcc-9 gcc-8 gcc-7 clang gcc" + ;; + *) + list_of_compilers="gcc cl cc" + ;; +esac + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +if test -n "$ac_tool_prefix"; then + for ac_prog in $list_of_compilers do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 @@ -2446,7 +2381,7 @@ fi fi if test -z "$CC"; then ac_ct_CC=$CC - for ac_prog in cl.exe + for ac_prog in $list_of_compilers do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 @@ -2501,8 +2436,6 @@ esac fi fi -fi - test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} @@ -2996,34 +2929,6 @@ ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $ ac_compiler_gnu=$ac_cv_c_compiler_gnu -ac_aux_dir= -for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do - if test -f "$ac_dir/install-sh"; then - ac_aux_dir=$ac_dir - ac_install_sh="$ac_aux_dir/install-sh -c" - break - elif test -f "$ac_dir/install.sh"; then - ac_aux_dir=$ac_dir - ac_install_sh="$ac_aux_dir/install.sh -c" - break - elif test -f "$ac_dir/shtool"; then - ac_aux_dir=$ac_dir - ac_install_sh="$ac_aux_dir/shtool install -c" - break - fi -done -if test -z "$ac_aux_dir"; then - as_fn_error $? "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5 -fi - -# These three variables are undocumented and unsupported, -# and are intended to be withdrawn in a future Autoconf release. -# They can cause serious problems if a builder's source tree is in a directory -# whose full name contains unusual characters. -ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. -ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. -ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. - # Find a good install program. We prefer a C program (faster), # so one script is as good as another. But avoid the broken or @@ -3122,77 +3027,6 @@ test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' # find system type (using this macro means we must include # the files install-sh, config.sub, and config.guess (all from # the autoconf distribution) in our source tree!) -# Make sure we can run config.sub. -$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || - as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5 - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5 -$as_echo_n "checking build system type... " >&6; } -if ${ac_cv_build+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_build_alias=$build_alias -test "x$ac_build_alias" = x && - ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"` -test "x$ac_build_alias" = x && - as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5 -ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` || - as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5 - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5 -$as_echo "$ac_cv_build" >&6; } -case $ac_cv_build in -*-*-*) ;; -*) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;; -esac -build=$ac_cv_build -ac_save_IFS=$IFS; IFS='-' -set x $ac_cv_build -shift -build_cpu=$1 -build_vendor=$2 -shift; shift -# Remember, the first character of IFS is used to create $*, -# except with old shells: -build_os=$* -IFS=$ac_save_IFS -case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5 -$as_echo_n "checking host system type... " >&6; } -if ${ac_cv_host+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test "x$host_alias" = x; then - ac_cv_host=$ac_cv_build -else - ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` || - as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5 -fi - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5 -$as_echo "$ac_cv_host" >&6; } -case $ac_cv_host in -*-*-*) ;; -*) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;; -esac -host=$ac_cv_host -ac_save_IFS=$IFS; IFS='-' -set x $ac_cv_host -shift -host_cpu=$1 -host_vendor=$2 -shift; shift -# Remember, the first character of IFS is used to create $*, -# except with old shells: -host_os=$* -IFS=$ac_save_IFS -case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking target system type" >&5 $as_echo_n "checking target system type... " >&6; } if ${ac_cv_target+:} false; then : diff --git a/configure.ac b/configure.ac index e89778ff1..6f03a1e1d 100644 --- a/configure.ac +++ b/configure.ac @@ -46,7 +46,22 @@ fi # for @CC@ in output files; you have to do this even if you don't # care about @CC@, because system feature tests later on in # the ./configure script will expect $CC to be set right -AC_PROG_CC + +# AC_CANONICAL_HOST is needed to access the 'host_os' variable +AC_CANONICAL_HOST + +# Detect the target system +case "${host_os}" in + darwin*) + list_of_compilers="gcc-9 gcc-8 gcc-7 clang gcc" + ;; + *) + list_of_compilers="gcc cl cc" + ;; +esac + +AC_PROG_CC([$list_of_compilers]) + AC_PROG_INSTALL From 45b6fe501987baae666b845ca082f5de2b64558c Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Tue, 21 Jan 2020 12:41:18 +0100 Subject: [PATCH 28/36] Be more flexible with content of host_os --- configure | 5 ++++- configure.ac | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/configure b/configure index d9849273a..620f6f7c6 100755 --- a/configure +++ b/configure @@ -2323,7 +2323,10 @@ case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac # Detect the target system case "${host_os}" in - darwin*) + *darwin*) + list_of_compilers="gcc-9 gcc-8 gcc-7 clang gcc" + ;; + *macos*) list_of_compilers="gcc-9 gcc-8 gcc-7 clang gcc" ;; *) diff --git a/configure.ac b/configure.ac index 6f03a1e1d..a039f3a01 100644 --- a/configure.ac +++ b/configure.ac @@ -52,7 +52,10 @@ AC_CANONICAL_HOST # Detect the target system case "${host_os}" in - darwin*) + *darwin*) + list_of_compilers="gcc-9 gcc-8 gcc-7 clang gcc" + ;; + *macos*) list_of_compilers="gcc-9 gcc-8 gcc-7 clang gcc" ;; *) From 01715a4a1f1c738b95a65b29e454cffb9a3d1d00 Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Tue, 21 Jan 2020 13:45:15 +0100 Subject: [PATCH 29/36] test if case distinction for macos works --- configure | 4 ++-- configure.ac | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/configure b/configure index 620f6f7c6..4f0d9740b 100755 --- a/configure +++ b/configure @@ -2324,10 +2324,10 @@ case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac # Detect the target system case "${host_os}" in *darwin*) - list_of_compilers="gcc-9 gcc-8 gcc-7 clang gcc" + list_of_compilers="gcc-9 gcc-8 gcc-7 clang" ;; *macos*) - list_of_compilers="gcc-9 gcc-8 gcc-7 clang gcc" + list_of_compilers="gcc-9 gcc-8 gcc-7 clang" ;; *) list_of_compilers="gcc cl cc" diff --git a/configure.ac b/configure.ac index a039f3a01..d882ae377 100644 --- a/configure.ac +++ b/configure.ac @@ -53,10 +53,10 @@ AC_CANONICAL_HOST # Detect the target system case "${host_os}" in *darwin*) - list_of_compilers="gcc-9 gcc-8 gcc-7 clang gcc" + list_of_compilers="gcc-9 gcc-8 gcc-7 clang" ;; *macos*) - list_of_compilers="gcc-9 gcc-8 gcc-7 clang gcc" + list_of_compilers="gcc-9 gcc-8 gcc-7 clang" ;; *) list_of_compilers="gcc cl cc" From 47e33006796abc210098628f9c53722272587dd8 Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Tue, 21 Jan 2020 14:19:28 +0100 Subject: [PATCH 30/36] Set CC=gcc-9 for MacOS --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 6a31ae955..6126d3e5b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,7 @@ language: c sudo: required before_install: - - if [ "$TRAVIS_OS_NAME" = "osx" ]; then brew list gcc || brew install gcc; fi + - if [ "$TRAVIS_OS_NAME" = "osx" ]; then brew list gcc || brew install gcc && CC=gcc-9; fi install: wget https://raw.githubusercontent.com/ocaml/ocaml-ci-scripts/master/.travis-opam.sh script: OPAMWITHDOC=false bash -ex .travis-opam.sh env: From 7870313add5360089bf2c74937597ad1e47d8097 Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Wed, 22 Jan 2020 14:02:31 +0100 Subject: [PATCH 31/36] Support tgmath.h in newer versions of GCC --- src/cil.ml | 3 ++ src/frontc/cabs2cil.ml | 68 +++++++++++++++++++++++++++++++++++++--- test/small1/c99-tgmath.c | 15 ++++++++- 3 files changed, 80 insertions(+), 6 deletions(-) diff --git a/src/cil.ml b/src/cil.ml index 5d9c58c67..3bf6f6f5c 100755 --- a/src/cil.ml +++ b/src/cil.ml @@ -3161,6 +3161,9 @@ let initGccBuiltins () : unit = H.add h "__builtin_ia32_unpcklps" (v4sfType, [v4sfType; v4sfType], false); H.add h "__builtin_ia32_maxps" (v4sfType, [v4sfType; v4sfType], false); + (** tgmath in newer versions of GCC *) + H.add h "__builtin_tgmath" (TVoid[Attr("overloaded",[])], [ ], true); + (* Atomic Builtins These builtins have an overloaded return type, hence the "magic" void type with __overloaded__ attribute, used to infer return type from parameters in diff --git a/src/frontc/cabs2cil.ml b/src/frontc/cabs2cil.ml index de36604de..648db8913 100644 --- a/src/frontc/cabs2cil.ml +++ b/src/frontc/cabs2cil.ml @@ -4220,13 +4220,14 @@ and doExp (asconst: bool) (* This expression is used as a constant *) fv.vname = "__builtin_va_arg" || fv.vname = "__builtin_va_start" || fv.vname = "__builtin_expect" || - fv.vname = "__builtin_next_arg" + fv.vname = "__builtin_next_arg" || + fv.vname = "__builtin_tgmath" | _ -> false in - let isBuiltinChooseExpr = + let isBuiltinChooseExprOrTgmath = match f'' with Lval (Var fv, NoOffset) -> - fv.vname = "__builtin_choose_expr" + fv.vname = "__builtin_choose_expr" || fv.vname = "__builtin_tgmath" | _ -> false in @@ -4282,7 +4283,7 @@ and doExp (asconst: bool) (* This expression is used as a constant *) let (ss, args') = loop args in let (sa, a', at) = force_right_to_left_evaluation (doExp false a (AExp None)) in - if isBuiltinChooseExpr then + if isBuiltinChooseExprOrTgmath then (* This built-in function is analogous to the `? :' * operator in C, except that the expression returned * has its type unaltered by promotion rules. @@ -4337,7 +4338,64 @@ and doExp (asconst: bool) (* This expression is used as a constant *) http://gcc.gnu.org/onlinedocs/gcc/_005f_005fsync-Builtins.html#g_t_005f_005fsync-Builtins http://gcc.gnu.org/onlinedocs/gcc/_005f_005fatomic-Builtins.html *) - if !resType' = TVoid[Attr("overloaded",[])] then begin + if !resType' = TVoid[Attr("overloaded",[])] then + if fv.vname = "__builtin_tgmath" then + match !pargs with + | ptr :: _ -> + begin match typeOf ptr with + (* as per https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html *) + | TPtr (TFun (r, args, _, _), _) -> + (* the first pointer to a function determines how many arguments all functions take *) + let numArgs = List.length (argsToList args) in + if numArgs = 0 then + ignore (warn "EINS Invalid call to %s" fv.vname) + else + let rec lastn n list acc = + if n = 0 then + acc + else + lastn (n-1) list ((List.nth list (List.length list -n)) :: acc) + in + let rec firstn n list acc = + if n = 0 then + acc + else + match list with + | l::ls -> firstn (n-1) ls (l :: acc) + | [] -> acc + in + (* to determine the return type, there are several options: *) + let retTypes e = match typeOf e with | TPtr(TFun(r, _, _ , _), _) -> r | _ -> E.s("Invalid call to __builtin_tgmath") in + let retTypes = List.map retTypes (firstn (List.length !pargs - numArgs) !pargs []) in + if List.for_all (fun x -> typeSig x = typeSig r) retTypes then + (* a) all function pointers have the same return type *) + resType' := r + else + (* b) all function pointers have return type t, so we need to determine which one is called *) + (* to get the correct return type *) + (* the arguments passed to the function are the last numArgs arguments. Get their types *) + let argTypes = List.map typeOf (lastn numArgs !pargs []) in + (* the return type is determined by the resulting arithmetic conversion of the argument types *) + (* at least for the uses of this to realize tgmath.h. This could be potentially incorrect for other *) + (* uses of __builtin_tgmath *) + let r = List.fold_left arithmeticConversion (List.nth argTypes 0) argTypes in + (* if the t we determined here is complex, but the return types of all the fptrs are not, the return *) + (* type should not be complex *) + let isComplex t = match t with + | TFloat(f, _) -> f = FComplexFloat || f = FComplexDouble || f = FComplexLongDouble + | _ -> false + in + if List.for_all (fun x -> not (isComplex x)) retTypes then + resType' := typeOfRealAndImagComponents r + else + resType' := r + | _ -> + ignore (warn "Invalid call to %s" fv.vname) + end + | _ -> + ignore (warn "Invalid call to %s" fv.vname) + else + begin match !pargs with ptr :: _ -> begin match typeOf ptr with TPtr (vtype, _) -> diff --git a/test/small1/c99-tgmath.c b/test/small1/c99-tgmath.c index 5597fbbf8..ee0ef4b26 100644 --- a/test/small1/c99-tgmath.c +++ b/test/small1/c99-tgmath.c @@ -5,16 +5,29 @@ int main(void) { + float f1 = 1.0f; + f1 = fabs(f1); float f = fabs(1.0f); double d = fabs(1.0); - long l = fabs(1.0l); + long double l = fabs(1.0l); float _Complex fc = 3.25f + 0.1if; + // should directly have type float and not float _Complex float f2 = fabs(fc); double _Complex fcd = 3.25 + 0.1i; double f2d = fabs(fcd); + // Those two calls should both have the same return type + double _Complex idk = pow(fc, fcd); + double _Complex idk2 = pow(fcd, fc); + + // Those should directly have type int not going through any casting + int i = ilogb(d); + int j = ilogb(f); + + long double idk3 = scalbn(l, 1); + if(f != 1.0f) E(1); From 8e255cb314971f89deaa1799d5d4575fcee2dba3 Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Wed, 22 Jan 2020 14:14:59 +0100 Subject: [PATCH 32/36] Remove __const__ from asm Was not ignored in GCC 7 (with warning), causes error in GCC 9 --- test/small1/asm4.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/test/small1/asm4.c b/test/small1/asm4.c index 193044b2c..6d4a65878 100644 --- a/test/small1/asm4.c +++ b/test/small1/asm4.c @@ -34,7 +34,7 @@ main (int argc, gu64t2 = (__extension__ ( 0xa77a0a30026b631dULL)) ; - + (void)( { if (!( sizeof (gint8) == 1 )) g_log (((gchar*) 0) , G_LOG_LEVEL_ERROR, "file %s: line %d (%s): assertion failed: (%s)", "type-test.c", 47, __PRETTY_FUNCTION__, "sizeof (gint8) == 1"); }) ; (void)( { if (!( sizeof (gint16) == 2 )) g_log (((gchar*) 0) , G_LOG_LEVEL_ERROR, "file %s: line %d (%s): assertion failed: (%s)", "type-test.c", 48, __PRETTY_FUNCTION__, "sizeof (gint16) == 2"); }) ; (void)( { if (!( sizeof (gint32) == 4 )) g_log (((gchar*) 0) , G_LOG_LEVEL_ERROR, "file %s: line %d (%s): assertion failed: (%s)", "type-test.c", 49, __PRETTY_FUNCTION__, "sizeof (gint32) == 4"); }) ; @@ -42,13 +42,11 @@ main (int argc, (void)( { if (!( sizeof (gint64) == 8 )) g_log (((gchar*) 0) , G_LOG_LEVEL_ERROR, "file %s: line %d (%s): assertion failed: (%s)", "type-test.c", 51, __PRETTY_FUNCTION__, "sizeof (gint64) == 8"); }) ; #if defined(i386) || defined(__x86_64__) - (void)( { if (!( ((__extension__ ({ register guint16 __v; if (__builtin_constant_p ( gu16t1 )) __v = ((guint16) ( (((guint16) ( gu16t1 ) & (guint16) 0x00ffU) << 8) | (((guint16) ( gu16t1 ) & (guint16) 0xff00U) >> 8))) ; else __asm__ __const__ ("rorw $8, %w0" : "=r" (__v) : "0" ((guint16) ( gu16t1 ))); __v; })) ) == gu16t2 )) g_log (((gchar*) 0) , G_LOG_LEVEL_ERROR, "file %s: line %d (%s): assertion failed: (%s)", "type-test.c", 54, __PRETTY_FUNCTION__, "GUINT16_SWAP_LE_BE (gu16t1) == gu16t2"); }) ; - (void)( { if (!( ((__extension__ ({ register guint32 __v; if (__builtin_constant_p ( gu32t1 )) __v = ((guint32) ( (((guint32) ( gu32t1 ) & (guint32) 0x000000ffU) << 24) | (((guint32) ( gu32t1 ) & (guint32) 0x0000ff00U) << 8) | (((guint32) ( gu32t1 ) & (guint32) 0x00ff0000U) >> 8) | (((guint32) ( gu32t1 ) & (guint32) 0xff000000U) >> 24))) ; else __asm__ __const__ ("rorw $8, %w0\n\t" "rorl $16, %0\n\t" "rorw $8, %w0" : "=r" (__v) : "0" ((guint32) ( gu32t1 ))); __v; })) ) == gu32t2 )) g_log (((gchar*) 0) , G_LOG_LEVEL_ERROR, "file %s: line %d (%s): assertion failed: (%s)", "type-test.c", 55, __PRETTY_FUNCTION__, "GUINT32_SWAP_LE_BE (gu32t1) == gu32t2"); }) ; + (void)( { if (!( ((__extension__ ({ register guint16 __v; if (__builtin_constant_p ( gu16t1 )) __v = ((guint16) ( (((guint16) ( gu16t1 ) & (guint16) 0x00ffU) << 8) | (((guint16) ( gu16t1 ) & (guint16) 0xff00U) >> 8))) ; else __asm__ ("rorw $8, %w0" : "=r" (__v) : "0" ((guint16) ( gu16t1 ))); __v; })) ) == gu16t2 )) g_log (((gchar*) 0) , G_LOG_LEVEL_ERROR, "file %s: line %d (%s): assertion failed: (%s)", "type-test.c", 54, __PRETTY_FUNCTION__, "GUINT16_SWAP_LE_BE (gu16t1) == gu16t2"); }) ; + (void)( { if (!( ((__extension__ ({ register guint32 __v; if (__builtin_constant_p ( gu32t1 )) __v = ((guint32) ( (((guint32) ( gu32t1 ) & (guint32) 0x000000ffU) << 24) | (((guint32) ( gu32t1 ) & (guint32) 0x0000ff00U) << 8) | (((guint32) ( gu32t1 ) & (guint32) 0x00ff0000U) >> 8) | (((guint32) ( gu32t1 ) & (guint32) 0xff000000U) >> 24))) ; else __asm__ ("rorw $8, %w0\n\t" "rorl $16, %0\n\t" "rorw $8, %w0" : "=r" (__v) : "0" ((guint32) ( gu32t1 ))); __v; })) ) == gu32t2 )) g_log (((gchar*) 0) , G_LOG_LEVEL_ERROR, "file %s: line %d (%s): assertion failed: (%s)", "type-test.c", 55, __PRETTY_FUNCTION__, "GUINT32_SWAP_LE_BE (gu32t1) == gu32t2"); }) ; - (void)( { if (!( ((__extension__ ({ union { guint64 __ll; guint32 __l[2]; } __r; if (__builtin_constant_p ( gu64t1 )) __r.__ll = ((guint64) ( (((guint64) ( gu64t1 ) & (guint64) (__extension__ ( 0x00000000000000ffULL)) ) << 56) | (((guint64) ( gu64t1 ) & (guint64) (__extension__ ( 0x000000000000ff00ULL)) ) << 40) | (((guint64) ( gu64t1 ) & (guint64) (__extension__ ( 0x0000000000ff0000ULL)) ) << 24) | (((guint64) ( gu64t1 ) & (guint64) (__extension__ ( 0x00000000ff000000ULL)) ) << 8) | (((guint64) ( gu64t1 ) & (guint64) (__extension__ ( 0x000000ff00000000ULL)) ) >> 8) | (((guint64) ( gu64t1 ) & (guint64) (__extension__ ( 0x0000ff0000000000ULL)) ) >> 24) | (((guint64) ( gu64t1 ) & (guint64) (__extension__ ( 0x00ff000000000000ULL)) ) >> 40) | (((guint64) ( gu64t1 ) & (guint64) (__extension__ ( 0xff00000000000000ULL)) ) >> 56))) ; else { union { guint64 __ll; guint32 __l[2]; } __w; __w.__ll = ((guint64) gu64t1 ); __r.__l[0] = ((__extension__ ({ register guint32 __v; if (__builtin_constant_p ( __w.__l[1] )) __v = ((guint32) ( (((guint32) ( __w.__l[1] ) & (guint32) 0x000000ffU) << 24) | (((guint32) ( __w.__l[1] ) & (guint32) 0x0000ff00U) << 8) | (((guint32) ( __w.__l[1] ) & (guint32) 0x00ff0000U) >> 8) | (((guint32) ( __w.__l[1] ) & (guint32) 0xff000000U) >> 24))) ; else __asm__ __const__ ("rorw $8, %w0\n\t" "rorl $16, %0\n\t" "rorw $8, %w0" : "=r" (__v) : "0" ((guint32) ( __w.__l[1] ))); __v; })) ) ; __r.__l[1] = ((__extension__ ({ register guint32 __v; if (__builtin_constant_p ( __w.__l[0] )) __v = ((guint32) ( (((guint32) ( __w.__l[0] ) & (guint32) 0x000000ffU) << 24) | (((guint32) ( __w.__l[0] ) & (guint32) 0x0000ff00U) << 8) | (((guint32) ( __w.__l[0] ) & (guint32) 0x00ff0000U) >> 8) | (((guint32) ( __w.__l[0] ) & (guint32) 0xff000000U) >> 24))) ; else __asm__ __const__ ("rorw $8, %w0\n\t" "rorl $16, %0\n\t" "rorw $8, %w0" : "=r" (__v) : "0" ((guint32) ( __w.__l[0] ))); __v; })) ) ; } __r.__ll; })) ) == gu64t2 )) g_log (((gchar*) 0) , G_LOG_LEVEL_ERROR, "file %s: line %d (%s): assertion failed: (%s)", "type-test.c", 57, __PRETTY_FUNCTION__, "GUINT64_SWAP_LE_BE (gu64t1) == gu64t2"); }) ; + (void)( { if (!( ((__extension__ ({ union { guint64 __ll; guint32 __l[2]; } __r; if (__builtin_constant_p ( gu64t1 )) __r.__ll = ((guint64) ( (((guint64) ( gu64t1 ) & (guint64) (__extension__ ( 0x00000000000000ffULL)) ) << 56) | (((guint64) ( gu64t1 ) & (guint64) (__extension__ ( 0x000000000000ff00ULL)) ) << 40) | (((guint64) ( gu64t1 ) & (guint64) (__extension__ ( 0x0000000000ff0000ULL)) ) << 24) | (((guint64) ( gu64t1 ) & (guint64) (__extension__ ( 0x00000000ff000000ULL)) ) << 8) | (((guint64) ( gu64t1 ) & (guint64) (__extension__ ( 0x000000ff00000000ULL)) ) >> 8) | (((guint64) ( gu64t1 ) & (guint64) (__extension__ ( 0x0000ff0000000000ULL)) ) >> 24) | (((guint64) ( gu64t1 ) & (guint64) (__extension__ ( 0x00ff000000000000ULL)) ) >> 40) | (((guint64) ( gu64t1 ) & (guint64) (__extension__ ( 0xff00000000000000ULL)) ) >> 56))) ; else { union { guint64 __ll; guint32 __l[2]; } __w; __w.__ll = ((guint64) gu64t1 ); __r.__l[0] = ((__extension__ ({ register guint32 __v; if (__builtin_constant_p ( __w.__l[1] )) __v = ((guint32) ( (((guint32) ( __w.__l[1] ) & (guint32) 0x000000ffU) << 24) | (((guint32) ( __w.__l[1] ) & (guint32) 0x0000ff00U) << 8) | (((guint32) ( __w.__l[1] ) & (guint32) 0x00ff0000U) >> 8) | (((guint32) ( __w.__l[1] ) & (guint32) 0xff000000U) >> 24))) ; else __asm__ ("rorw $8, %w0\n\t" "rorl $16, %0\n\t" "rorw $8, %w0" : "=r" (__v) : "0" ((guint32) ( __w.__l[1] ))); __v; })) ) ; __r.__l[1] = ((__extension__ ({ register guint32 __v; if (__builtin_constant_p ( __w.__l[0] )) __v = ((guint32) ( (((guint32) ( __w.__l[0] ) & (guint32) 0x000000ffU) << 24) | (((guint32) ( __w.__l[0] ) & (guint32) 0x0000ff00U) << 8) | (((guint32) ( __w.__l[0] ) & (guint32) 0x00ff0000U) >> 8) | (((guint32) ( __w.__l[0] ) & (guint32) 0xff000000U) >> 24))) ; else __asm__ ("rorw $8, %w0\n\t" "rorl $16, %0\n\t" "rorw $8, %w0" : "=r" (__v) : "0" ((guint32) ( __w.__l[0] ))); __v; })) ) ; } __r.__ll; })) ) == gu64t2 )) g_log (((gchar*) 0) , G_LOG_LEVEL_ERROR, "file %s: line %d (%s): assertion failed: (%s)", "type-test.c", 57, __PRETTY_FUNCTION__, "GUINT64_SWAP_LE_BE (gu64t1) == gu64t2"); }) ; #endif return 0; } - - From be553fe189b29c0efde0680bb8d27e0946a29ab2 Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Wed, 22 Jan 2020 15:30:59 +0100 Subject: [PATCH 33/36] Pass CC to all the tests even if CC is called directly and not via cilly --- test/Makefile.gcc | 4 +++- test/testcil.pl | 9 ++++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/test/Makefile.gcc b/test/Makefile.gcc index 8fae4e343..2b460f11f 100644 --- a/test/Makefile.gcc +++ b/test/Makefile.gcc @@ -4,7 +4,9 @@ COMPILERNAME := GNUCC -CC := gcc +ifeq (,$(findstring gcc,$(CC))) + CC := gcc +endif ifdef RELEASELIB # sm: I will leave this here, but only use it for compiling our runtime lib CFLAGS := -D_GNUCC -Wall -O3 diff --git a/test/testcil.pl b/test/testcil.pl index 3af1030de..a6eec6bf2 100644 --- a/test/testcil.pl +++ b/test/testcil.pl @@ -121,10 +121,17 @@ sub addTest { my %patterns = %commonerrors; my $kind; + my $ccvar; + if ($ENV{'CC'} ne "gcc") { + $ccvar = "CC=$ENV{'CC'}"; + } else { + $ccvar = ""; + } + my $tst = $self->newTest(Name => $name, Dir => ".", - Cmd => "$make " . $name . $theargs, + Cmd => "$ccvar $make " . $name . $theargs, Group => [ ], Patterns => \%patterns); # Add the extra fields From 4adf96cd6aee0dc395495a847b0c45874da33cbe Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Thu, 23 Jan 2020 10:00:55 +0100 Subject: [PATCH 34/36] Travis: also test with Ocaml 4.08 and 4.09 --- .travis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index 6126d3e5b..c6c095309 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,6 +9,8 @@ env: - OCAML_VERSION=4.05 - OCAML_VERSION=4.06 - OCAML_VERSION=4.07 + - OCAML_VERSION=4.08 + - OCAML_VERSION=4.09 os: - linux - osx From 7daa70944da1b1b272ff73be00e0d0e68d4bbc64 Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Thu, 23 Jan 2020 10:40:11 +0100 Subject: [PATCH 35/36] Travis: Remove sudo. Build config validation warns: deprecated key sudo (The key `sudo` has no effect anymore.) --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index c6c095309..6a4cbf7c4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,4 @@ language: c -sudo: required before_install: - if [ "$TRAVIS_OS_NAME" = "osx" ]; then brew list gcc || brew install gcc && CC=gcc-9; fi install: wget https://raw.githubusercontent.com/ocaml/ocaml-ci-scripts/master/.travis-opam.sh From 3a5a738c77791aaa80cac0f1421c315b9b18aef0 Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Thu, 23 Jan 2020 14:06:49 +0100 Subject: [PATCH 36/36] testrun/longBlock: Use ocamlfind Instead of giving include path directly, hopefullt this fixes failing build for OCaml 4.08 on MacOS --- test/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Makefile b/test/Makefile index a71355146..3fb56c6ff 100644 --- a/test/Makefile +++ b/test/Makefile @@ -268,7 +268,7 @@ else endif testrun/% : $(SMALL1)/%.ml - $(CAMLC) -I $(OBJDIR) -I +../zarith unix.$(CMXA) str.$(CMXA) zarith.$(CMXA) \ + ocamlfind $(CAMLC) -I $(OBJDIR) -package zarith unix.$(CMXA) str.$(CMXA) zarith.$(CMXA) \ cil.$(CMXA) \ $(EXEOUT) $(basename $<).exe $< $(basename $<).exe