diff options
23 files changed, 376 insertions, 1 deletions
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 146fa02..b0db389 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,28 @@ +2010-05-25 Iain Sandoe <iains@gcc.gnu.org> + + * obj-c++.dg/torture/tls/trivial.mm: New. + * obj-c++.dg/torture/tls/thr-init-1.mm: New. + * obj-c++.dg/torture/tls/thr-init-2.mm: New. + * obj-c++.dg/torture/tls/thr-init-3.mm: New. + * obj-c++.dg/torture/tls/diag-1.mm: New. + * obj-c++.dg/torture/tls/tls.exp: New. + * obj-c++.dg/torture/trivial.mm: New. + * obj-c++.dg/torture/dg-torture.exp: New. + * obj-c++.dg/dg.exp: Gather tests explicitly from the source dir. + * obj-c++.dg/tls/trivial.m: New. + * obj-c++.dg/tls/init-1.mm: New. + * obj-c++.dg/tls/diag-1.mm: New. + * obj-c++.dg/tls/init-2.mm: New. + * obj-c++.dg/tls/diag-2.mm: New. + * obj-c++.dg/tls/diag-3.mm: New. + * obj-c++.dg/tls/diag-4.mm: New. + * obj-c++.dg/tls/static-1.mm: New. + * obj-c++.dg/tls/tls.exp: New. + * obj-c++.dg/tls/diag-5.mm: New. + * obj-c++.dg/tls/static-1a.mm: New. + * objc-obj-c++-shared/Object1.mm: New. + * lib/obj-c++-dg.exp (obj-c++-dg-runtest): New proc. + 2010-05-24 Iain Sandoe <iains@gcc.gnu.org> PR ObjC++/43689 diff --git a/gcc/testsuite/lib/obj-c++-dg.exp b/gcc/testsuite/lib/obj-c++-dg.exp index dc8c560..dbdeaa2 100644 --- a/gcc/testsuite/lib/obj-c++-dg.exp +++ b/gcc/testsuite/lib/obj-c++-dg.exp @@ -26,3 +26,9 @@ proc obj-c++-dg-test { prog do_what extra_tool_flags } { proc obj-c++-dg-prune { system text } { return [gcc-dg-prune $system $text] } + +# Modified dg-runtest that can cycle through a list of optimization options +# as c-torture does. +proc obj-c++-dg-runtest { testcases default-extra-flags } { + return [gcc-dg-runtest $testcases ${default-extra-flags}] +} diff --git a/gcc/testsuite/obj-c++.dg/dg.exp b/gcc/testsuite/obj-c++.dg/dg.exp index 1097464..bff972b 100644 --- a/gcc/testsuite/obj-c++.dg/dg.exp +++ b/gcc/testsuite/obj-c++.dg/dg.exp @@ -28,7 +28,7 @@ if ![info exists DEFAULT_OBJCXXFLAGS] then { dg-init # Gather a list of all tests. -set tests [lsort [find $srcdir/$subdir *.mm]] +set tests [lsort [glob -nocomplain $srcdir/$subdir/*.mm]] # Main loop. dg-runtest $tests "-fgnu-runtime" $DEFAULT_OBJCXXFLAGS diff --git a/gcc/testsuite/obj-c++.dg/tls/diag-1.mm b/gcc/testsuite/obj-c++.dg/tls/diag-1.mm new file mode 100644 index 0000000..7c3245d --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/tls/diag-1.mm @@ -0,0 +1,12 @@ +// Valid __thread specifiers. +// { dg-require-effective-target tls } + +__thread int g1; +extern __thread int g2; +static __thread int g3; + +void foo() +{ + extern __thread int l1; + static __thread int l2; +} diff --git a/gcc/testsuite/obj-c++.dg/tls/diag-2.mm b/gcc/testsuite/obj-c++.dg/tls/diag-2.mm new file mode 100644 index 0000000..de88eb1 --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/tls/diag-2.mm @@ -0,0 +1,26 @@ +/* Invalid __thread specifiers. */ +/* { dg-require-effective-target tls } */ + +__thread extern int g1; /* { dg-error "'__thread' before 'extern'" } */ +__thread static int g2; /* { dg-error "'__thread' before 'static'" } */ +__thread __thread int g3; /* { dg-error "duplicate '__thread'" } */ +typedef __thread int g4; /* { dg-error "multiple storage classes" } */ + +void foo() +{ + __thread int l1; /* { dg-error "implicitly auto and declared '__thread'" } */ + auto __thread int l2; /* { dg-error "multiple storage classes" } */ + __thread extern int l3; /* { dg-error "'__thread' before 'extern'" } */ + register __thread int l4; /* { dg-error "multiple storage classes" } */ +} + +__thread void f1 (); /* { dg-error "storage class '__thread' invalid for function 'f1'" } */ +extern __thread void f2 (); /* { dg-error "storage class '__thread' invalid for function 'f2'" } */ +static __thread void f3 (); /* { dg-error "storage class '__thread' invalid for function 'f3'" } */ +__thread void f4 () { } /* { dg-error "storage class '__thread' invalid for function 'f4'" } */ + +void bar(__thread int p1); /* { dg-error "(invalid in parameter)|(specified for parameter)" } */ + +struct A { + __thread int i; /* { dg-error "storage class specified for 'i'" } */ +}; diff --git a/gcc/testsuite/obj-c++.dg/tls/diag-3.mm b/gcc/testsuite/obj-c++.dg/tls/diag-3.mm new file mode 100644 index 0000000..0a597b2 --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/tls/diag-3.mm @@ -0,0 +1,11 @@ +/* Report invalid extern and __thread combinations. */ +/* { dg-require-effective-target tls } */ + +extern int j; /* { dg-error "previously declared here" } */ +__thread int j; /* { dg-error "follows non-thread-local" } */ + +extern __thread int i; /* { dg-error "previously declared here" } */ +int i; /* { dg-error "follows thread-local" } */ + +extern __thread int k; /* This is fine. */ +__thread int k; diff --git a/gcc/testsuite/obj-c++.dg/tls/diag-4.mm b/gcc/testsuite/obj-c++.dg/tls/diag-4.mm new file mode 100644 index 0000000..10ac2aa --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/tls/diag-4.mm @@ -0,0 +1,10 @@ +/* Invalid __thread specifiers. */ +/* { dg-require-effective-target tls } */ + +__thread typedef int g4; /* { dg-error "multiple storage classes in declaration of" } */ + +void foo() +{ + __thread auto int l2; /* { dg-error "multiple storage classes in declaration of" } */ + __thread register int l4; /* { dg-error "multiple storage classes in declaration of" } */ +} diff --git a/gcc/testsuite/obj-c++.dg/tls/diag-5.mm b/gcc/testsuite/obj-c++.dg/tls/diag-5.mm new file mode 100644 index 0000000..07ecd3f --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/tls/diag-5.mm @@ -0,0 +1,4 @@ +/* __thread specifiers on empty declarations. */ +/* { dg-require-effective-target tls } */ + +__thread struct foo; /* { dg-warning "qualifiers can only be specified for objects and functions" } */ diff --git a/gcc/testsuite/obj-c++.dg/tls/init-1.mm b/gcc/testsuite/obj-c++.dg/tls/init-1.mm new file mode 100644 index 0000000..9430887 --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/tls/init-1.mm @@ -0,0 +1,14 @@ +/* Invalid initializations. */ +/* { dg-require-effective-target tls } */ + +__thread int i = 42; + +static int j; +__thread int *p = &j; + +/* Note that this is valid in C++ (unlike C) as a run-time initialization. */ +int *q = &i; + +/* Valid because "const int k" is an integral constant expression in C++. */ +__thread const int k = 42; +__thread const int l = k;
\ No newline at end of file diff --git a/gcc/testsuite/obj-c++.dg/tls/init-2.mm b/gcc/testsuite/obj-c++.dg/tls/init-2.mm new file mode 100644 index 0000000..dc886ba --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/tls/init-2.mm @@ -0,0 +1,14 @@ +/* Invalid initializations. */ +/* { dg-require-effective-target tls } */ + +extern __thread int i; +__thread int *p = &i; /* { dg-error "dynamically initialized" } */ + +extern int f(); +__thread int j = f(); /* { dg-error "dynamically initialized" } */ + +struct S +{ + S(); +}; +__thread S s; /* { dg-error "" } two errors here */ diff --git a/gcc/testsuite/obj-c++.dg/tls/static-1.mm b/gcc/testsuite/obj-c++.dg/tls/static-1.mm new file mode 100644 index 0000000..2d20b88 --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/tls/static-1.mm @@ -0,0 +1,30 @@ +// { dg-do run } +// { dg-require-effective-target tls } +// { dg-additional-sources "static-1a.mm" } + +extern "C" { +extern void abort (); +} +extern int test (); + +struct A +{ + static __thread int i; +}; + +__thread int A::i = 8; + +int +main () +{ + if (A::i != 8) + abort (); + + if (test ()) + abort (); + + if (A::i != 17) + abort (); + + return 0; +} diff --git a/gcc/testsuite/obj-c++.dg/tls/static-1a.mm b/gcc/testsuite/obj-c++.dg/tls/static-1a.mm new file mode 100644 index 0000000..4097420 --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/tls/static-1a.mm @@ -0,0 +1,17 @@ +// { dg-skip-if "Additional Source File" *-*-* "*" "" } +// This is the additional source file for test static-1.mm + +struct A +{ + static __thread int i; +}; + +int +test () +{ + if (A::i != 8) + return 1; + + A::i = 17; + return 0; +} diff --git a/gcc/testsuite/obj-c++.dg/tls/tls.exp b/gcc/testsuite/obj-c++.dg/tls/tls.exp new file mode 100644 index 0000000..a4ba639 --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/tls/tls.exp @@ -0,0 +1,25 @@ +# Load support procs. +load_lib obj-c++-dg.exp + +# If a testcase doesn't have special options, use these. +global DEFAULT_OBJCXXFLAGS +if ![info exists DEFAULT_OBJCXXFLAGS] then { + set DEFAULT_OBJCXXFLAGS " -ansi -pedantic-errors -Wno-long-long" +} + +# Initialize `dg'. +dg-init + +# Gather a list of all tests. +set tests [lsort [glob -nocomplain $srcdir/$subdir/*.mm]] + +# Main loop. +dg-runtest $tests "-fgnu-runtime" $DEFAULT_OBJCXXFLAGS + +# darwin targets can also run code with the NeXT runtime. +if [istarget "*-*-darwin*" ] { +dg-runtest $tests "-fnext-runtime" $DEFAULT_OBJCXXFLAGS +} + +# All done. +dg-finish diff --git a/gcc/testsuite/obj-c++.dg/tls/trivial.m b/gcc/testsuite/obj-c++.dg/tls/trivial.m new file mode 100644 index 0000000..e2b8f45 --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/tls/trivial.m @@ -0,0 +1,3 @@ +// { dg-require-effective-target tls } + +__thread int i; diff --git a/gcc/testsuite/obj-c++.dg/torture/dg-torture.exp b/gcc/testsuite/obj-c++.dg/torture/dg-torture.exp new file mode 100644 index 0000000..9ef34e9 --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/torture/dg-torture.exp @@ -0,0 +1,17 @@ +# This harness is for tests that should be run at all optimisation levels. + +load_lib obj-c++-dg.exp + +dg-init + +# Gather a list of all tests. +set tests [lsort [glob -nocomplain $srcdir/$subdir/*.mm]] + +obj-c++-dg-runtest $tests "-fgnu-runtime" + +# darwin targets can also run code with the NeXT runtime. +if [istarget "*-*-darwin*" ] { + obj-c++-dg-runtest $tests "-fnext-runtime" +} + +dg-finish diff --git a/gcc/testsuite/obj-c++.dg/torture/tls/diag-1.mm b/gcc/testsuite/obj-c++.dg/torture/tls/diag-1.mm new file mode 100644 index 0000000..7c3245d --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/torture/tls/diag-1.mm @@ -0,0 +1,12 @@ +// Valid __thread specifiers. +// { dg-require-effective-target tls } + +__thread int g1; +extern __thread int g2; +static __thread int g3; + +void foo() +{ + extern __thread int l1; + static __thread int l2; +} diff --git a/gcc/testsuite/obj-c++.dg/torture/tls/thr-init-1.mm b/gcc/testsuite/obj-c++.dg/torture/tls/thr-init-1.mm new file mode 100644 index 0000000..45d67f4 --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/torture/tls/thr-init-1.mm @@ -0,0 +1,23 @@ +// { dg-require-effective-target tls } +// { dg-do run } +extern "C" { +extern void abort (); +} + +static __thread int fstat = 1; + +int test_code(int b) +{ + fstat += b ; + return fstat; +} + +int main (int ac, char *av[]) +{ + int a = test_code(1); + + if ( a != 2 || fstat != 2 ) + abort (); + + return 0; +} diff --git a/gcc/testsuite/obj-c++.dg/torture/tls/thr-init-2.mm b/gcc/testsuite/obj-c++.dg/torture/tls/thr-init-2.mm new file mode 100644 index 0000000..a96ae94 --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/torture/tls/thr-init-2.mm @@ -0,0 +1,44 @@ +// { dg-require-effective-target tls } +// { dg-do run } + +extern "C" { +extern void abort (); +} + +__thread int glb =1 ; + +static __thread int fstat = 2; + +int fa(int a) +{ +static __thread int as = 3; + as += a ; + return as; +} + +int fb(int b) +{ +static __thread int bs = 4; + bs += b ; + glb = bs; + return bs; +} + +int main (int ac, char *av[]) +{ + int a = 1; + + a = fa(fstat); + if ( a != 5 ) + abort () ; + + a = fa(glb); + if ( a != 6 ) + abort () ; + + a = fb(a); + if ( a != 10 || glb != 10 ) + abort () ; + + return 0; +}
\ No newline at end of file diff --git a/gcc/testsuite/obj-c++.dg/torture/tls/thr-init-3.mm b/gcc/testsuite/obj-c++.dg/torture/tls/thr-init-3.mm new file mode 100644 index 0000000..98d1ba4 --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/torture/tls/thr-init-3.mm @@ -0,0 +1,41 @@ +/* { dg-require-effective-target tls } */ +/* { dg-do run } */ +/* { dg-xfail-if "PR44140" { *-*-* } { "-flto" "-fwhopr" } { "" } } */ +/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */ +/* { dg-additional-sources "../../../objc-obj-c++-shared/Object1.mm" } */ + +#include "../../../objc-obj-c++-shared/Object1.h" +extern "C" { +extern void abort (); +} + +@interface tsObj: Object { + int ai ; +} + +- (int) fa:(int) n; + +@end + +@implementation tsObj + +- (int) fa:(int) n +{ +static __thread int as = 3; + as += n ; + return as ; +} + +@end + +int main (int ac, char *av[]) +{ + int a ; + tsObj *to = [tsObj new]; + + a = [to fa:5]; + if ( a != 8 ) + abort () ; + + return 0; +} diff --git a/gcc/testsuite/obj-c++.dg/torture/tls/tls.exp b/gcc/testsuite/obj-c++.dg/torture/tls/tls.exp new file mode 100644 index 0000000..6d06680 --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/torture/tls/tls.exp @@ -0,0 +1,16 @@ +# This harness is for tests that should be run at all optimisation levels. + +load_lib obj-c++-dg.exp + +dg-init +# Gather a list of all tests. +set tests [lsort [glob -nocomplain $srcdir/$subdir/*.mm]] + +obj-c++-dg-runtest $tests "-fgnu-runtime" + +# darwin targets can also run code with the NeXT runtime. +if [istarget "*-*-darwin*" ] { + obj-c++-dg-runtest $tests "-fnext-runtime" +} + +dg-finish diff --git a/gcc/testsuite/obj-c++.dg/torture/tls/trivial.mm b/gcc/testsuite/obj-c++.dg/torture/tls/trivial.mm new file mode 100644 index 0000000..e2b8f45 --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/torture/tls/trivial.mm @@ -0,0 +1,3 @@ +// { dg-require-effective-target tls } + +__thread int i; diff --git a/gcc/testsuite/obj-c++.dg/torture/trivial.mm b/gcc/testsuite/obj-c++.dg/torture/trivial.mm new file mode 100644 index 0000000..8d776b7 --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/torture/trivial.mm @@ -0,0 +1,11 @@ +// { dg-do run } +// { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } +// { dg-additional-sources "../../objc-obj-c++-shared/Object1.mm" } + +#import "../../objc-obj-c++-shared/Object1.h" + +int main(void) +{ + [Object class]; + return 0; +} diff --git a/gcc/testsuite/objc-obj-c++-shared/Object1.mm b/gcc/testsuite/objc-obj-c++-shared/Object1.mm new file mode 100644 index 0000000..f435a75 --- /dev/null +++ b/gcc/testsuite/objc-obj-c++-shared/Object1.mm @@ -0,0 +1,11 @@ +#import "Object1.h" +/* This will generate the code if required - as determined by + the headr above. It is kept like this to keep one code file + shared between dg-xxxx tests that can ask for an extra source + and the objc/{compile,execute}/xxx tests that have to include + the implementation explicitly. + + For cases/targets that don't require the generation of the + Object implementation, this should result in an empty object. +*/ +#import "Object1-implementation.h" |