diff mbox series

Fix PR c++/85400

Message ID 32444455.vUGMIimiic@polaris
State New
Headers show
Series Fix PR c++/85400 | expand

Commit Message

Eric Botcazou April 26, 2018, 1:42 p.m. UTC
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  <ebotcazou@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  <ebotcazou@adacore.com>

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

Comments

Jason Merrill April 26, 2018, 6:49 p.m. UTC | #1
On Thu, Apr 26, 2018 at 9:42 AM, Eric Botcazou <ebotcazou@adacore.com> wrote:
> 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  <ebotcazou@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.

It seems like we're likely to need the same thing when we get to
make_decl_one_only by other paths; perhaps we should put this
recalculation in a cxx_make_decl_one_only.

Jason
Eric Botcazou April 30, 2018, 8:43 a.m. UTC | #2
> It seems like we're likely to need the same thing when we get to
> make_decl_one_only by other paths; perhaps we should put this
> recalculation in a cxx_make_decl_one_only.

There are 4 calls to make_decl_one_only in the cp/ directory: the one at stake 
here in comdat_linkage, 1 in maybe_make_one_only, 1 in get_guard and 1 in 
get_tls_init_fn.  The last 2 don't need the recalculation, especially the 3rd 
one which makes a copy of the TLS model.

There are 3 calls to maybe_make_one_only in the cp/directory: 1 from 
start_preparsed_function, 1 from mark_decl_instantiated and 1 one from 
import_export_decl but guarded by DECL_FUNCTION_MEMBER_P.  The 1st and 3rd 
don't need the recalculation.

So it isn't clear to me if a cxx_make_decl_one_only is the way to go.  Maybe 
doing the recalculation in comdat_linkage and maybe_make_one_only only would 
be sufficient.
Eric Botcazou May 9, 2018, 10:05 a.m. UTC | #3
> So it isn't clear to me if a cxx_make_decl_one_only is the way to go.  Maybe
> doing the recalculation in comdat_linkage and maybe_make_one_only only
> would be sufficient.

Patch to that effect attached, tested on x86-64/Linux, OK for mainline?


2018-05-09  Eric Botcazou  <ebotcazou@adacore.com>

cp/
	PR c++/85400
	* decl2.c (adjust_var_decl_tls_model): New static function.
	(comdat_linkage): Call it on a variable.
	(maybe_make_one_only): Likewise.

c-family/
	* c-attribs.c (handle_visibility_attribute): Do not set no_add_attrs.
Jason Merrill May 9, 2018, 2:36 p.m. UTC | #4
OK.

On Wed, May 9, 2018 at 6:05 AM, Eric Botcazou <ebotcazou@adacore.com> wrote:
>> So it isn't clear to me if a cxx_make_decl_one_only is the way to go.  Maybe
>> doing the recalculation in comdat_linkage and maybe_make_one_only only
>> would be sufficient.
>
> Patch to that effect attached, tested on x86-64/Linux, OK for mainline?
>
>
> 2018-05-09  Eric Botcazou  <ebotcazou@adacore.com>
>
> cp/
>         PR c++/85400
>         * decl2.c (adjust_var_decl_tls_model): New static function.
>         (comdat_linkage): Call it on a variable.
>         (maybe_make_one_only): Likewise.
>
> c-family/
>         * c-attribs.c (handle_visibility_attribute): Do not set no_add_attrs.
>
> --
> Eric Botcazou
Jakub Jelinek June 11, 2018, 1:30 p.m. UTC | #5
On Wed, May 09, 2018 at 12:05:34PM +0200, Eric Botcazou wrote:
> > So it isn't clear to me if a cxx_make_decl_one_only is the way to go.  Maybe
> > doing the recalculation in comdat_linkage and maybe_make_one_only only
> > would be sufficient.
> 
> Patch to that effect attached, tested on x86-64/Linux, OK for mainline?
> 
> 
> 2018-05-09  Eric Botcazou  <ebotcazou@adacore.com>
> 
> cp/
> 	PR c++/85400
> 	* decl2.c (adjust_var_decl_tls_model): New static function.
> 	(comdat_linkage): Call it on a variable.
> 	(maybe_make_one_only): Likewise.
> 
> c-family/
> 	* c-attribs.c (handle_visibility_attribute): Do not set no_add_attrs.

Eric, do you plan to backport this to release branches?

> Index: cp/decl2.c
> ===================================================================
> --- cp/decl2.c	(revision 259642)
> +++ cp/decl2.c	(working copy)
> @@ -1838,6 +1838,17 @@ mark_vtable_entries (tree decl)
>      }
>  }
>  
> +/* Adjust the TLS model on variable DECL if need be, typically after
> +   the linkage of DECL has been modified.  */
> +
> +static void
> +adjust_var_decl_tls_model (tree decl)
> +{
> +  if (CP_DECL_THREAD_LOCAL_P (decl)
> +      && !lookup_attribute ("tls_model", DECL_ATTRIBUTES (decl)))
> +    set_decl_tls_model (decl, decl_default_tls_model (decl));
> +}
> +
>  /* Set DECL up to have the closest approximation of "initialized common"
>     linkage available.  */
>  
> @@ -1888,6 +1899,9 @@ comdat_linkage (tree decl)
>  
>    if (TREE_PUBLIC (decl))
>      DECL_COMDAT (decl) = 1;
> +
> +  if (VAR_P (decl))
> +    adjust_var_decl_tls_model (decl);
>  }
>  
>  /* For win32 we also want to put explicit instantiations in
> @@ -1926,6 +1940,8 @@ maybe_make_one_only (tree decl)
>  	  /* Mark it needed so we don't forget to emit it.  */
>            node->forced_by_abi = true;
>  	  TREE_USED (decl) = 1;
> +
> +	  adjust_var_decl_tls_model (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);


	Jakub
Eric Botcazou June 11, 2018, 9:37 p.m. UTC | #6
> Eric, do you plan to backport this to release branches?

I don't think so, it isn't a regression and the workaround is trivial.
diff mbox series

Patch

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