Hi,

for the attached testcase compiled/linked with -shared -fPIC -O, the Solaris 
linker chokes on SPARC because the generated code uses the local-dynamic TLS 
model for a global symbol:

ld: fatal: relocation error: R_SPARC_TLS_LDM_HI22: file /var/tmp//ccKG6GQC.o: 
symbol Test::blah(int)::mything: bound to: /var/tmp//ccKG6GQC.o: relocation 
illegal when not bound to object being created

The symbol is a local TLS symbol defined in an inline method of a class so it 
is first local so decl_default_tls_model chooses TLS_MODEL_LOCAL_DYNAMIC.  But 
then it is "commonized" by the C++ front-end:

/* If a local static variable is declared in an inline function, or if
   we have a weak definition, we must endeavor to create only one
   instance of the variable at link-time.  */

which calls comdat_linkage, which in turn calls make_decl_one_only, which 
makes it weak and public, so unsuitable for the local-dynamic TLS model.

The proposed fix is to reset the TLS model after the commonization, but of 
course only if no tls_model attribute was set on the variable, hence the fix 
for handle_tls_model_attribute.  Tested on x86-64/Linux, OK for mainline?


2018-04-26  Eric Botcazou  <ebotca...@adacore.com>

cp/
        PR c++/85400
        * decl.c (cp_finish_decl): Recompute the TLS model after commonizing
        a TLS-local variable, unless it has got an explicit TLS model.
c-family/
        * c-attribs.c (handle_visibility_attribute): Do not set no_add_attrs.


2018-04-26  Eric Botcazou  <ebotca...@adacore.com>

        * g++.dg/tls/pr85400.C: New test.

-- 
Eric Botcazou
Index: cp/decl.c
===================================================================
--- cp/decl.c	(revision 259642)
+++ cp/decl.c	(working copy)
@@ -7216,9 +7216,14 @@ cp_finish_decl (tree decl, tree init, bo
 	{
 	  layout_var_decl (decl);
 	  maybe_commonize_var (decl);
+
+	  /* This needs to be adjusted after the linkage is set.  */
+	  if (CP_DECL_THREAD_LOCAL_P (decl)
+	      && !lookup_attribute ("tls_model", DECL_ATTRIBUTES (decl)))
+	    set_decl_tls_model (decl, decl_default_tls_model (decl));
 	}
 
-      /* This needs to happen after the linkage is set. */
+      /* This needs to happen after the linkage is set.  */
       determine_visibility (decl);
 
       if (var_definition_p && TREE_STATIC (decl))
Index: c-family/c-attribs.c
===================================================================
--- c-family/c-attribs.c	(revision 259642)
+++ c-family/c-attribs.c	(working copy)
@@ -2299,14 +2299,13 @@ handle_visibility_attribute (tree *node,
 
 static tree
 handle_tls_model_attribute (tree *node, tree name, tree args,
-			    int ARG_UNUSED (flags), bool *no_add_attrs)
+			    int ARG_UNUSED (flags),
+			    bool *ARG_UNUSED (no_add_attrs))
 {
   tree id;
   tree decl = *node;
   enum tls_model kind;
 
-  *no_add_attrs = true;
-
   if (!VAR_P (decl) || !DECL_THREAD_LOCAL_P (decl))
     {
       warning (OPT_Wattributes, "%qE attribute ignored", name);
// PR c++/85400
// Testcase by Brian Vandenberg <phant...@gmail.com>

// { dg-do link { target c++11 } }
// { dg-require-effective-target fpic }
// { dg-require-effective-target shared }
// { dg-require-effective-target tls }
// { dg-options "-shared -fPIC -O" }
// { dg-add-options tls }

struct Test
{
  int blah (int y)
  {
    thread_local int mything = 3;
    mything = y > 0 ? y : mything;
    return mything;
  }
};

int stuff (Test& test, int y)
{
  return test.blah(y);
}

Reply via email to