diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 1b2d16661ab..bcbddc7fbd9 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,10 @@ +2005-11-08 Jakub Jelinek + + PR c++/19450 + * decl.c (redeclaration_error_message): Issue diagnostics about + olddecl and newdecl disagreement on __thread property. + (grokdeclarator): Set DECL_TLS_MODEL on class static variables. + 2005-11-08 Jason Merrill PR c++/21123 diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index c5fe6585996..7263b32d2ee 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -2014,6 +2014,18 @@ redeclaration_error_message (tree newdecl, tree olddecl) return NULL; } + else if (TREE_CODE (newdecl) == VAR_DECL + && DECL_THREAD_LOCAL_P (newdecl) != DECL_THREAD_LOCAL_P (olddecl)) + { + /* Only variables can be thread-local, and all declarations must + agree on this property. */ + if (DECL_THREAD_LOCAL_P (newdecl)) + return "thread-local declaration of %q#D follows " + "non-thread-local declaration"; + else + return "non-thread-local declaration of %q#D follows " + "thread-local declaration"; + } else if (toplevel_bindings_p () || DECL_NAMESPACE_SCOPE_P (newdecl)) { /* Objects declared at top level: */ @@ -8216,6 +8228,17 @@ grokdeclarator (const cp_declarator *declarator, is considered undefined until an out-of-class definition is provided. */ DECL_EXTERNAL (decl) = 1; + + if (thread_p) + { + if (targetm.have_tls) + DECL_TLS_MODEL (decl) = decl_default_tls_model (decl); + else + /* A mere warning is sure to result in improper + semantics at runtime. Don't bother to allow this to + compile. */ + error ("thread-local storage not supported for this target"); + } } else { diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 644433544f2..8058bb84e5c 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,11 @@ +2005-11-08 Jakub Jelinek + + PR c++/19450 + * g++.dg/tls/diag-3.C: New test. + * g++.dg/tls/diag-4.C: New test. + * g++.dg/tls/static-1.C: New test. + * g++.dg/tls/static-1a.cc: New file. + 2005-11-08 Diego Novillo PR 23046 diff --git a/gcc/testsuite/g++.dg/tls/diag-3.C b/gcc/testsuite/g++.dg/tls/diag-3.C new file mode 100644 index 00000000000..ae2b6ce211f --- /dev/null +++ b/gcc/testsuite/g++.dg/tls/diag-3.C @@ -0,0 +1,10 @@ +// Report invalid extern and __thread combinations. + +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/g++.dg/tls/diag-4.C b/gcc/testsuite/g++.dg/tls/diag-4.C new file mode 100644 index 00000000000..3b840f1e7b9 --- /dev/null +++ b/gcc/testsuite/g++.dg/tls/diag-4.C @@ -0,0 +1,9 @@ +/* Invalid __thread specifiers. */ + +__thread typedef int g4; /* { dg-error "multiple storage classes" } */ + +void foo() +{ + __thread auto int l2; /* { dg-error "multiple storage classes" } */ + __thread register int l4; /* { dg-error "multiple storage classes" } */ +} diff --git a/gcc/testsuite/g++.dg/tls/static-1.C b/gcc/testsuite/g++.dg/tls/static-1.C new file mode 100644 index 00000000000..3cbcbec2d31 --- /dev/null +++ b/gcc/testsuite/g++.dg/tls/static-1.C @@ -0,0 +1,28 @@ +// { dg-do run } +// { dg-options "-O2" } +// { dg-additional-sources "static-1a.cc" } + +extern "C" 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/g++.dg/tls/static-1a.cc b/gcc/testsuite/g++.dg/tls/static-1a.cc new file mode 100644 index 00000000000..c87efdb8ecd --- /dev/null +++ b/gcc/testsuite/g++.dg/tls/static-1a.cc @@ -0,0 +1,18 @@ +// { dg-do run } +// { dg-options "-O2" } +// { dg-additional-sources "static-1a.cc" } + +struct A +{ + static __thread int i; +}; + +int +test () +{ + if (A::i != 8) + return 1; + + A::i = 17; + return 0; +}