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:
Iain Sandoe 2010-05-25 08:28:44 +00:00
parent 9d4545b28e
commit 683fc98b74
23 changed files with 376 additions and 1 deletions

View File

@ -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

View File

@ -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}]
}

View File

@ -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

View File

@ -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;
}

View File

@ -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'" } */
};

View File

@ -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;

View File

@ -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" } */
}

View File

@ -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" } */

View File

@ -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;

View File

@ -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 */

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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

View File

@ -0,0 +1,3 @@
// { dg-require-effective-target tls }
__thread int i;

View File

@ -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

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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

View File

@ -0,0 +1,3 @@
// { dg-require-effective-target tls }
__thread int i;

View File

@ -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;
}

View File

@ -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"