decl.c (check_tag_decl): Handle RID_THREAD.
* decl.c (check_tag_decl): Handle RID_THREAD. (obscure_complex_init): Reject run-time init of tls. (grokvardecl, grokdeclarator): Handle RID_THREAD. * lex.c (reswords): Add __thread. (rid_to_yy): Map RID_THREAD to SCSPEC. * g++.dg/dg.exp: Prune the tls subdirectory. * g++.dg/tls/tls.exp, g++.dg/tls/trivial.C: New. * g++.dg/tls/diag-1.C, g++.dg/tls/diag-2.C: New. * g++.dg/tls/init-1.C: New. From-SVN: r53754
This commit is contained in:
parent
c711ba8e2e
commit
7a1f3f5f3b
@ -1,3 +1,11 @@
|
||||
2002-05-22 Richard Henderson <rth@redhat.com>
|
||||
|
||||
* decl.c (check_tag_decl): Handle RID_THREAD.
|
||||
(obscure_complex_init): Reject run-time init of tls.
|
||||
(grokvardecl, grokdeclarator): Handle RID_THREAD.
|
||||
* lex.c (reswords): Add __thread.
|
||||
(rid_to_yy): Map RID_THREAD to SCSPEC.
|
||||
|
||||
2002-05-22 Neil Booth <neil@daikokuya.demon.co.uk>
|
||||
|
||||
* cp-lang.c (LANG_HOOKS_POST_OPTIONS): Use c_common_post_options.
|
||||
|
@ -7106,7 +7106,8 @@ check_tag_decl (declspecs)
|
||||
|| value == ridpointers[(int) RID_VIRTUAL]
|
||||
|| value == ridpointers[(int) RID_CONST]
|
||||
|| value == ridpointers[(int) RID_VOLATILE]
|
||||
|| value == ridpointers[(int) RID_EXPLICIT])
|
||||
|| value == ridpointers[(int) RID_EXPLICIT]
|
||||
|| value == ridpointers[(int) RID_THREAD])
|
||||
ob_modifier = value;
|
||||
}
|
||||
|
||||
@ -7580,6 +7581,12 @@ static tree
|
||||
obscure_complex_init (decl, init)
|
||||
tree decl, init;
|
||||
{
|
||||
if (DECL_THREAD_LOCAL (decl))
|
||||
{
|
||||
error ("run-time initialization of thread-local storage");
|
||||
return NULL_TREE;
|
||||
}
|
||||
|
||||
if (! flag_no_inline && TREE_STATIC (decl))
|
||||
{
|
||||
if (extract_init (decl, init))
|
||||
@ -9274,6 +9281,16 @@ grokvardecl (type, declarator, specbits_in, initialized, constp, in_namespace)
|
||||
TREE_PUBLIC (decl) = DECL_EXTERNAL (decl);
|
||||
}
|
||||
|
||||
if (RIDBIT_SETP (RID_THREAD, specbits))
|
||||
{
|
||||
if (targetm.have_tls)
|
||||
DECL_THREAD_LOCAL (decl) = 1;
|
||||
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");
|
||||
}
|
||||
|
||||
if (TREE_PUBLIC (decl))
|
||||
{
|
||||
/* [basic.link]: A name with no linkage (notably, the name of a class
|
||||
@ -10176,10 +10193,22 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
|
||||
}
|
||||
else if (RIDBIT_SETP (i, specbits))
|
||||
pedwarn ("duplicate `%s'", IDENTIFIER_POINTER (id));
|
||||
|
||||
/* Diagnose "__thread extern". Recall that this list
|
||||
is in the reverse order seen in the text. */
|
||||
if (i == (int)RID_THREAD)
|
||||
{
|
||||
if (RIDBIT_SETP (RID_EXTERN, specbits))
|
||||
error ("`__thread' before `extern'");
|
||||
if (RIDBIT_SETP (RID_STATIC, specbits))
|
||||
error ("`__thread' before `static'");
|
||||
}
|
||||
|
||||
if (i == (int)RID_EXTERN
|
||||
&& TREE_PURPOSE (spec) == error_mark_node)
|
||||
/* This extern was part of a language linkage. */
|
||||
extern_langp = 1;
|
||||
|
||||
RIDBIT_SET (i, specbits);
|
||||
goto found;
|
||||
}
|
||||
@ -10476,6 +10505,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
|
||||
{
|
||||
if (RIDBIT_SETP (RID_STATIC, specbits)) nclasses++;
|
||||
if (RIDBIT_SETP (RID_EXTERN, specbits) && !extern_langp) nclasses++;
|
||||
if (RIDBIT_SETP (RID_THREAD, specbits)) nclasses++;
|
||||
if (decl_context == PARM && nclasses > 0)
|
||||
error ("storage class specifiers invalid in parameter declarations");
|
||||
if (RIDBIT_SETP (RID_TYPEDEF, specbits))
|
||||
@ -10507,6 +10537,13 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
|
||||
/* Warn about storage classes that are invalid for certain
|
||||
kinds of declarations (parameters, typenames, etc.). */
|
||||
|
||||
/* "static __thread" and "extern __thread" are allowed. */
|
||||
if (nclasses == 2
|
||||
&& RIDBIT_SETP (RID_THREAD, specbits)
|
||||
&& (RIDBIT_SETP (RID_EXTERN, specbits)
|
||||
|| RIDBIT_SETP (RID_STATIC, specbits)))
|
||||
nclasses = 1;
|
||||
|
||||
if (nclasses > 1)
|
||||
error ("multiple storage classes in declaration of `%s'", name);
|
||||
else if (decl_context != NORMAL && nclasses > 0)
|
||||
@ -10562,6 +10599,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
|
||||
RIDBIT_RESET (RID_REGISTER, specbits);
|
||||
RIDBIT_RESET (RID_AUTO, specbits);
|
||||
RIDBIT_RESET (RID_EXTERN, specbits);
|
||||
RIDBIT_RESET (RID_THREAD, specbits);
|
||||
}
|
||||
}
|
||||
else if (RIDBIT_SETP (RID_EXTERN, specbits) && initialized && !funcdef_flag)
|
||||
@ -10584,6 +10622,14 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
|
||||
if (RIDBIT_SETP (RID_AUTO, specbits))
|
||||
error ("top-level declaration of `%s' specifies `auto'", name);
|
||||
}
|
||||
else if (RIDBIT_SETP (RID_THREAD, specbits)
|
||||
&& !RIDBIT_SETP (RID_EXTERN, specbits)
|
||||
&& !RIDBIT_SETP (RID_STATIC, specbits))
|
||||
{
|
||||
error ("function-scope `%s' implicitly auto and declared `__thread'",
|
||||
name);
|
||||
RIDBIT_RESET (RID_THREAD, specbits);
|
||||
}
|
||||
|
||||
if (nclasses > 0 && friendp)
|
||||
error ("storage class specifiers invalid in friend function declarations");
|
||||
@ -11784,6 +11830,8 @@ friend declaration requires class-key, i.e. `friend %#T'",
|
||||
error ("storage class `auto' invalid for function `%s'", name);
|
||||
else if (RIDBIT_SETP (RID_REGISTER, specbits))
|
||||
error ("storage class `register' invalid for function `%s'", name);
|
||||
else if (RIDBIT_SETP (RID_THREAD, specbits))
|
||||
error ("storage class `__thread' invalid for function `%s'", name);
|
||||
|
||||
/* Function declaration not at top level.
|
||||
Storage classes other than `extern' are not allowed
|
||||
|
@ -362,6 +362,7 @@ static const struct resword reswords[] =
|
||||
{ "__restrict__", RID_RESTRICT, 0 },
|
||||
{ "__signed", RID_SIGNED, 0 },
|
||||
{ "__signed__", RID_SIGNED, 0 },
|
||||
{ "__thread", RID_THREAD, 0 },
|
||||
{ "__typeof", RID_TYPEOF, 0 },
|
||||
{ "__typeof__", RID_TYPEOF, 0 },
|
||||
{ "__volatile", RID_VOLATILE, 0 },
|
||||
@ -467,7 +468,7 @@ const short rid_to_yy[RID_MAX] =
|
||||
/* RID_BOUNDED */ 0,
|
||||
/* RID_UNBOUNDED */ 0,
|
||||
/* RID_COMPLEX */ TYPESPEC,
|
||||
/* RID_THREAD */ 0,
|
||||
/* RID_THREAD */ SCSPEC,
|
||||
|
||||
/* C++ */
|
||||
/* RID_FRIEND */ SCSPEC,
|
||||
|
@ -1,3 +1,10 @@
|
||||
2002-05-22 Richard Henderson <rth@redhat.com>
|
||||
|
||||
* g++.dg/dg.exp: Prune the tls subdirectory.
|
||||
* g++.dg/tls/tls.exp, g++.dg/tls/trivial.C: New.
|
||||
* g++.dg/tls/diag-1.C, g++.dg/tls/diag-2.C: New.
|
||||
* g++.dg/tls/init-1.C: New.
|
||||
|
||||
2002-05-22 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
* gcc.dg/20020517-1.c: New test.
|
||||
@ -168,11 +175,11 @@ Mon May 20 10:51:35 2002 J"orn Rennecke <joern.rennecke@superh.com>
|
||||
|
||||
2002-05-02 Aldy Hernandez <aldyh@redhat.com>
|
||||
|
||||
* gcc.dg/altivec-8.c: New.
|
||||
* gcc.dg/altivec-8.c: New.
|
||||
|
||||
2002-05-01 Aldy Hernandez <aldyh@redhat.com>
|
||||
|
||||
* gcc.dg/altivec-7.c: New.
|
||||
* gcc.dg/altivec-7.c: New.
|
||||
|
||||
2002-04-29 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
@ -319,8 +326,8 @@ Wed Apr 24 21:38:36 2002 J"orn Rennecke <joern.rennecke@superh.com>
|
||||
|
||||
2002-04-18 Richard Henderson <rth@redhat.com>
|
||||
|
||||
* gcc.dg/20000906-1.c: Enable for all targets.
|
||||
* gcc.c-torture/compile/iftrap-2.c: New.
|
||||
* gcc.dg/20000906-1.c: Enable for all targets.
|
||||
* gcc.c-torture/compile/iftrap-2.c: New.
|
||||
|
||||
2002-04-18 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
@ -329,9 +336,9 @@ Wed Apr 24 21:38:36 2002 J"orn Rennecke <joern.rennecke@superh.com>
|
||||
|
||||
2002-04-18 Richard Henderson <rth@redhat.com>
|
||||
|
||||
* gcc.c-torture/compile/iftrap-1.c: New.
|
||||
* gcc.dg/iftrap-1.c: Adjust for ia64.
|
||||
* gcc.dg/iftrap-2.c: New.
|
||||
* gcc.c-torture/compile/iftrap-1.c: New.
|
||||
* gcc.dg/iftrap-1.c: Adjust for ia64.
|
||||
* gcc.dg/iftrap-2.c: New.
|
||||
|
||||
2002-04-18 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
|
@ -31,10 +31,11 @@ dg-init
|
||||
# Gather a list of all tests, with the exception of those in directories
|
||||
# that are handled specially.
|
||||
set all [lsort [find $srcdir/$subdir *.C]]
|
||||
set tests [prune [prune [prune [prune $all $srcdir/$subdir/special/*] \
|
||||
$srcdir/$subdir/debug/*] \
|
||||
$srcdir/$subdir/gcov/*] \
|
||||
$srcdir/$subdir/bprob/*]
|
||||
set tests [prune $tests $srcdir/$subdir/bprob/*]
|
||||
set tests [prune $tests $srcdir/$subdir/debug/*]
|
||||
set tests [prune $tests $srcdir/$subdir/gcov/*]
|
||||
set tests [prune $tests $srcdir/$subdir/special/*]
|
||||
set tests [prune $tests $srcdir/$subdir/tls/*]
|
||||
|
||||
# Main loop.
|
||||
dg-runtest $tests "" $DEFAULT_CXXFLAGS
|
||||
|
30
gcc/testsuite/g++.dg/tls/diag-1.C
Normal file
30
gcc/testsuite/g++.dg/tls/diag-1.C
Normal file
@ -0,0 +1,30 @@
|
||||
/* Valid __thread specifiers. */
|
||||
|
||||
__thread int g1;
|
||||
extern __thread int g2;
|
||||
static __thread int g3;
|
||||
|
||||
void foo()
|
||||
{
|
||||
extern __thread int l1;
|
||||
static __thread int l2;
|
||||
}
|
||||
|
||||
struct A {
|
||||
static __thread int i;
|
||||
};
|
||||
|
||||
__thread int A::i = 42;
|
||||
|
||||
template <typename T> struct B {
|
||||
static __thread T t;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
__thread T B<T>::t = 42;
|
||||
|
||||
void bar ()
|
||||
{
|
||||
int j = B<int>::t;
|
||||
int k = B<const int>::t;
|
||||
}
|
25
gcc/testsuite/g++.dg/tls/diag-2.C
Normal file
25
gcc/testsuite/g++.dg/tls/diag-2.C
Normal file
@ -0,0 +1,25 @@
|
||||
/* Invalid __thread specifiers. */
|
||||
|
||||
__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 "invalid for function" } */
|
||||
extern __thread void f2 (); /* { dg-error "invalid for function" } */
|
||||
static __thread void f3 (); /* { dg-error "invalid for function" } */
|
||||
__thread void f4 () { } /* { dg-error "invalid for function" } */
|
||||
|
||||
void bar(__thread int p1); /* { dg-error "(invalid in parameter)|(specified for parameter)" } */
|
||||
|
||||
struct A {
|
||||
__thread int i; /* { dg-error "specified for field" } */
|
||||
};
|
13
gcc/testsuite/g++.dg/tls/init-1.C
Normal file
13
gcc/testsuite/g++.dg/tls/init-1.C
Normal file
@ -0,0 +1,13 @@
|
||||
/* Valid initializations. */
|
||||
|
||||
__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;
|
13
gcc/testsuite/g++.dg/tls/init-2.C
Normal file
13
gcc/testsuite/g++.dg/tls/init-2.C
Normal file
@ -0,0 +1,13 @@
|
||||
/* Invalid initializations. */
|
||||
|
||||
extern __thread int i;
|
||||
__thread int *p = &i; /* { dg-error "run-time initialization" } */
|
||||
|
||||
extern int f();
|
||||
__thread int j = f(); /* { dg-error "run-time initialization" } */
|
||||
|
||||
struct S
|
||||
{
|
||||
S();
|
||||
};
|
||||
__thread S s; /* { dg-error "run-time initialization" } */
|
44
gcc/testsuite/g++.dg/tls/tls.exp
Normal file
44
gcc/testsuite/g++.dg/tls/tls.exp
Normal file
@ -0,0 +1,44 @@
|
||||
# Copyright (C) 2002 Free Software Foundation, Inc.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
# GCC testsuite that uses the `dg.exp' driver.
|
||||
|
||||
# Load support procs.
|
||||
load_lib g++-dg.exp
|
||||
|
||||
# Test for thread-local data supported by the platform. If it
|
||||
# isn't, everything will fail with the "not supported" message.
|
||||
|
||||
set comp_output [g++_target_compile \
|
||||
"$srcdir/$subdir/trivial.C" "trivial.S" assembly ""]
|
||||
if { [string match "*not supported*" $comp_output] } {
|
||||
return 0
|
||||
}
|
||||
|
||||
# If a testcase doesn't have special options, use these.
|
||||
global DEFAULT_CXXFLAGS
|
||||
if ![info exists DEFAULT_CXXFLAGS] then {
|
||||
set DEFAULT_CXXFLAGS " -ansi -pedantic-errors -Wno-long-long"
|
||||
}
|
||||
|
||||
# Initialize `dg'.
|
||||
dg-init
|
||||
|
||||
# Main loop.
|
||||
dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.C]] "" $DEFAULT_CXXFLAGS
|
||||
|
||||
# All done.
|
||||
dg-finish
|
1
gcc/testsuite/g++.dg/tls/trivial.C
Normal file
1
gcc/testsuite/g++.dg/tls/trivial.C
Normal file
@ -0,0 +1 @@
|
||||
__thread int i;
|
Loading…
Reference in New Issue
Block a user