add TLS checks to ObjC++
* 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. From-SVN: r159810
This commit is contained in:
parent
9d4545b28e
commit
683fc98b74
|
@ -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
|
||||
|
|
|
@ -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}]
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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'" } */
|
||||
};
|
|
@ -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;
|
|
@ -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" } */
|
||||
}
|
|
@ -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" } */
|
|
@ -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;
|
|
@ -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 */
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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
|
|
@ -0,0 +1,3 @@
|
|||
// { dg-require-effective-target tls }
|
||||
|
||||
__thread int i;
|
|
@ -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
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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
|
|
@ -0,0 +1,3 @@
|
|||
// { dg-require-effective-target tls }
|
||||
|
||||
__thread int i;
|
|
@ -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;
|
||||
}
|
|
@ -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"
|
Loading…
Reference in New Issue