On 04/03/2013 05:50 PM, Rafael Espindola wrote:
Author: rafael
Date: Wed Apr  3 10:50:00 2013
New Revision: 178663

URL: http://llvm.org/viewvc/llvm-project?rev=178663&view=rev
Log:
Don't compute a patched/semantic storage class.

For variables and functions clang used to store two storage classes. The one
"as written" in the code and a patched one, which, for example, propagates
static to the following decls.

This apparently is from the days clang lacked linkage computation. It is now
redundant and this patch removes it.

[...]

+Storage Class
+^^^^^^^^^^^^^
+
+For each variable and function Clang used to keep the storage class as written
+in the source, the linkage and a semantic storage class. This was a bit
+redundant and the semantic storage class has been removed. The method
+getStorageClass now returns what is written it the source code for that decl.


Hello Rafael.

I think we found an occurrence of "patched/semantic storage class" that survived your commit. Here is the example showing the problem:

$ cat tl.cc
void foo() {
  thread_local int i;
}

If you pretty print it, you will see the "static" storage class specifier.

Please find attached a patch for review.
The patch avoids the patched/semantic storage class computation. As a necessary consequence, it also adapts the implementation of VarDecl methods hasLocalStorage() and isStaticLocal() to also check the thread storage specifier.

Cheers,
Enea.

P.S.: there actually are a couple of other occurrences of "patched/semantic storage class", but these are related to OpenCL/CUDA extensions and are not addressed in the patch.

Index: lib/Sema/SemaDecl.cpp
===================================================================
--- lib/Sema/SemaDecl.cpp	(revision 181515)
+++ lib/Sema/SemaDecl.cpp	(working copy)
@@ -4718,16 +4718,6 @@
     SC = SC_None;
   }
 
-  // C++11 [dcl.stc]p4:
-  //   When thread_local is applied to a variable of block scope the
-  //   storage-class-specifier static is implied if it does not appear
-  //   explicitly.
-  // Core issue: 'static' is not implied if the variable is declared 'extern'.
-  if (SCSpec == DeclSpec::SCS_unspecified &&
-      D.getDeclSpec().getThreadStorageClassSpec() ==
-          DeclSpec::TSCS_thread_local && DC->isFunctionOrMethod())
-    SC = SC_Static;
-
   IdentifierInfo *II = Name.getAsIdentifierInfo();
   if (!II) {
     Diag(D.getIdentifierLoc(), diag::err_bad_variable_name)
@@ -4885,12 +4875,23 @@
   NewVD->setLexicalDeclContext(CurContext);
 
   if (DeclSpec::TSCS TSCS = D.getDeclSpec().getThreadStorageClassSpec()) {
-    if (NewVD->hasLocalStorage())
+    if (NewVD->hasLocalStorage()) {
+      // C++11 [dcl.stc]p4:
+      //   When thread_local is applied to a variable of block scope the
+      //   storage-class-specifier static is implied if it does not appear
+      //   explicitly.
+      // Core issue: 'static' is not implied if the variable is declared
+      //   'extern'.
+      if (SCSpec == DeclSpec::SCS_unspecified &&
+          TSCS == DeclSpec::TSCS_thread_local &&
+          DC->isFunctionOrMethod())
+        NewVD->setTSCSpec(TSCS);
+      else
+        Diag(D.getDeclSpec().getThreadStorageClassSpecLoc(),
+             diag::err_thread_non_global)
+          << DeclSpec::getSpecifierName(TSCS);
+    } else if (!Context.getTargetInfo().isTLSSupported())
       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
       NewVD->setTSCSpec(TSCS);
@@ -5237,7 +5238,7 @@
       if (NewVD->isFileVarDecl())
         Diag(NewVD->getLocation(), diag::err_vla_decl_in_file_scope)
         << SizeRange;
-      else if (NewVD->getStorageClass() == SC_Static)
+      else if (NewVD->isStaticLocal())
         Diag(NewVD->getLocation(), diag::err_vla_decl_has_static_storage)
         << SizeRange;
       else
Index: test/SemaCXX/cxx11-thread-local-print.cpp
===================================================================
--- test/SemaCXX/cxx11-thread-local-print.cpp	(revision 181515)
+++ test/SemaCXX/cxx11-thread-local-print.cpp	(working copy)
@@ -7,3 +7,9 @@
 _Thread_local int c11_tl;
 thread_local int cxx11_tl;
 
+// CHECK: void foo() {
+// CHECK:     thread_local int cxx11_tl;
+// CHECK: }
+void foo() {
+    thread_local int cxx11_tl;
+}
Index: include/clang/AST/Decl.h
===================================================================
--- include/clang/AST/Decl.h	(revision 181515)
+++ include/clang/AST/Decl.h	(working copy)
@@ -797,7 +797,7 @@
   ///  is a non-static local variable.
   bool hasLocalStorage() const {
     if (getStorageClass() == SC_None)
-      return !isFileVarDecl();
+      return !isFileVarDecl() && getTSCSpec() != TSCS_thread_local;
 
     // Return true for:  Auto, Register.
     // Return false for: Extern, Static, PrivateExtern, OpenCLWorkGroupLocal.
@@ -808,7 +808,10 @@
   /// isStaticLocal - Returns true if a variable with function scope is a
   /// static local variable.
   bool isStaticLocal() const {
-    return getStorageClass() == SC_Static && !isFileVarDecl();
+    return (getStorageClass() == SC_Static ||
+            // C++11 [dcl.stc]p4
+            (getStorageClass() == SC_None && getTSCSpec() == TSCS_thread_local))
+      && !isFileVarDecl();
   }
 
   /// \brief Returns true if a variable has extern or __private_extern__
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to