The same error is given by Clang/LLVM.

Tested on x86_64-w64-mingw32, OK for the mainline?


2026-01-26  Eric Botcazou  <[email protected]>

        PR target/80881
        * attribs.cc (handle_dll_attribute): If TARGET_WIN32_TLS is 1,
        issue an error if either attribute is set on a TLS variable.


2026-01-26  Eric Botcazou  <[email protected]>

        * c-c++-common/tls-attr-dll.c: New test.

-- 
Eric Botcazou
diff --git a/gcc/attribs.cc b/gcc/attribs.cc
index db9a5c125ac..d802136655c 100644
--- a/gcc/attribs.cc
+++ b/gcc/attribs.cc
@@ -2007,10 +2007,16 @@ handle_dll_attribute (tree * pnode, tree name, tree args, int flags,
 	{
 	  if (DECL_INITIAL (node))
 	    {
-	      error ("variable %q+D definition is marked dllimport",
-		     node);
+	      error ("variable %q+D definition is marked dllimport", node);
 	      *no_add_attrs = true;
 	    }
+#if TARGET_WIN32_TLS
+	  else if (DECL_THREAD_LOCAL_P (node))
+	    {
+	      error ("thread-local variable %q+D declared as dllimport", node);
+	      *no_add_attrs = true;
+	    }
+#endif
 
 	  /* `extern' needn't be specified with dllimport.
 	     Specify `extern' now and hope for the best.  Sigh.  */
@@ -2034,6 +2040,13 @@ handle_dll_attribute (tree * pnode, tree name, tree args, int flags,
 	   && flag_keep_inline_dllexport)
     /* An exported function, even if inline, must be emitted.  */
     DECL_EXTERNAL (node) = 0;
+#if TARGET_WIN32_TLS
+  else if (VAR_P (node) && DECL_THREAD_LOCAL_P (node))
+    {
+      error ("thread-local variable %q+D declared as dllexport", node);
+      *no_add_attrs = true;
+    }
+#endif
 
   /*  Report error if symbol is not accessible at global scope.  */
   if (!TREE_PUBLIC (node) && VAR_OR_FUNCTION_DECL_P (node))
/* { dg-do compile { target i?86-*-mingw* x86_64-*-mingw* } } */

__declspec (dllimport) __thread int foo1; /* { dg-error "thread-local variable" } */

__declspec (dllexport) __thread int foo2; /* { dg-error "thread-local variable" } */

Reply via email to