]> granicus.if.org Git - clang/commitdiff
[cuda] Ignore "TLS unsupported by target" errors for host variables during device...
authorArtem Belevich <tra@google.com>
Mon, 27 Apr 2015 19:37:53 +0000 (19:37 +0000)
committerArtem Belevich <tra@google.com>
Mon, 27 Apr 2015 19:37:53 +0000 (19:37 +0000)
During device-side CUDA compilation clang currently complains about
all TLS variables, regardless of whether they are __host__ or
__device__.

This patch suppresses "TLS unsupported" errors for host variables
during device compilation and for device variables during host
compilation.

Differential Revision: http://reviews.llvm.org/D9269

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@235907 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Sema/SemaInternal.h
lib/Sema/SemaDecl.cpp
lib/Sema/SemaStmtAsm.cpp
test/SemaCUDA/qualifiers.cu

index 14e119c843ff453616522ad5b3662f4ecc91d182..60c6598287b7d210a5aec2151a8183aac7e0ba37 100644 (file)
@@ -48,6 +48,18 @@ inline bool IsVariableAConstantExpression(VarDecl *Var, ASTContext &Context) {
     Var->getAnyInitializer(DefVD) && DefVD->checkInitIsICE(); 
 }
 
+// Helper function to check whether D's attributes match current CUDA mode.
+// Decls with mismatched attributes and related diagnostics may have to be
+// ignored during this CUDA compilation pass.
+inline bool DeclAttrsMatchCUDAMode(const LangOptions &LangOpts, Decl *D) {
+  if (!LangOpts.CUDA || !D)
+    return true;
+  bool isDeviceSideDecl = D->hasAttr<CUDADeviceAttr>() ||
+                          D->hasAttr<CUDASharedAttr>() ||
+                          D->hasAttr<CUDAGlobalAttr>();
+  return isDeviceSideDecl == LangOpts.CUDAIsDevice;
+}
+
 // Directly mark a variable odr-used. Given a choice, prefer to use 
 // MarkVariableReferenced since it does additional checks and then 
 // calls MarkVarDeclODRUsed.
index 07dbdaf9968ffd13d5a4de515eedf304d53597c5..58e78387fd88311c59e83104806028695b070231 100644 (file)
@@ -5753,6 +5753,7 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
   if (IsLocalExternDecl)
     NewVD->setLocalExternDecl();
 
+  bool EmitTLSUnsupportedError = false;
   if (DeclSpec::TSCS TSCS = D.getDeclSpec().getThreadStorageClassSpec()) {
     // C++11 [dcl.stc]p4:
     //   When thread_local is applied to a variable of block scope the
@@ -5767,10 +5768,16 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
       Diag(D.getDeclSpec().getThreadStorageClassSpecLoc(),
            diag::err_thread_non_global)
         << DeclSpec::getSpecifierName(TSCS);
-    else if (!Context.getTargetInfo().isTLSSupported())
-      Diag(D.getDeclSpec().getThreadStorageClassSpecLoc(),
-           diag::err_thread_unsupported);
-    else
+    else if (!Context.getTargetInfo().isTLSSupported()) {
+      if (getLangOpts().CUDA)
+        // Postpone error emission until we've collected attributes required to
+        // figure out whether it's a host or device variable and whether the
+        // error should be ignored.
+        EmitTLSUnsupportedError = true;
+      else
+        Diag(D.getDeclSpec().getThreadStorageClassSpecLoc(),
+             diag::err_thread_unsupported);
+    } else
       NewVD->setTSCSpec(TSCS);
   }
 
@@ -5819,6 +5826,9 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
   ProcessDeclAttributes(S, NewVD, D);
 
   if (getLangOpts().CUDA) {
+    if (EmitTLSUnsupportedError && DeclAttrsMatchCUDAMode(getLangOpts(), NewVD))
+      Diag(D.getDeclSpec().getThreadStorageClassSpecLoc(),
+           diag::err_thread_unsupported);
     // CUDA B.2.5: "__shared__ and __constant__ variables have implied static
     // storage [duration]."
     if (SC == SC_None && S->getFnParent() != nullptr &&
index 179e207e76a027f1cd31c569efadf39064403712..9f48616ea5bffe67c7735e246bfe8352c7f96b12 100644 (file)
@@ -124,16 +124,8 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
   // The parser verifies that there is a string literal here.
   assert(AsmString->isAscii());
 
-  bool ValidateConstraints = true;
-  if (getLangOpts().CUDA) {
-    // In CUDA mode don't verify asm constraints in device functions during host
-    // compilation and vice versa.
-    bool InDeviceMode = getLangOpts().CUDAIsDevice;
-    FunctionDecl *FD = getCurFunctionDecl();
-    bool IsDeviceFunction =
-        FD && (FD->hasAttr<CUDADeviceAttr>() || FD->hasAttr<CUDAGlobalAttr>());
-    ValidateConstraints = IsDeviceFunction == InDeviceMode;
-  }
+  bool ValidateConstraints =
+      DeclAttrsMatchCUDAMode(getLangOpts(), getCurFunctionDecl());
 
   for (unsigned i = 0; i != NumOutputs; i++) {
     StringLiteral *Literal = Constraints[i];
index 42a80b8b38c77966f1aebc9b942f6ba1f300d55a..a5c8a6cd39487e89b9e1d637a00967aa2ebf3a3c 100644 (file)
@@ -1,7 +1,23 @@
-// RUN: %clang_cc1 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fsyntax-only -verify %s
+// RUN: %clang_cc1 -triple nvptx-unknown-cuda -fsyntax-only -verify -fcuda-is-device %s
 
 #include "Inputs/cuda.h"
 
+// Host (x86) supports TLS and device-side compilation should ignore
+// host variables. No errors in either case.
+int __thread host_tls_var;
+
+#if defined(__CUDA_ARCH__)
+// NVPTX does not support TLS
+__device__ int __thread device_tls_var; // expected-error {{thread-local storage is not supported for the current target}}
+__shared__ int __thread shared_tls_var; // expected-error {{thread-local storage is not supported for the current target}}
+#else
+// Device-side vars should not produce any errors during host-side
+// compilation.
+__device__ int __thread device_tls_var;
+__shared__ int __thread shared_tls_var;
+#endif
+
 __global__ void g1(int x) {}
 __global__ int g2(int x) { // expected-error {{must have void return type}}
   return 1;