Author: rnk Date: Wed Apr 30 22:16:47 2014 New Revision: 207734 URL: http://llvm.org/viewvc/llvm-project?rev=207734&view=rev Log: Add support for __declspec(thread) under -fms-extensions
Reviewers: rsmith Differential Revision: http://reviews.llvm.org/D3551 Added: cfe/trunk/test/SemaCXX/declspec-thread.cpp Modified: cfe/trunk/include/clang/AST/Decl.h cfe/trunk/include/clang/Basic/Attr.td cfe/trunk/include/clang/Basic/AttrDocs.td cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td cfe/trunk/lib/AST/Decl.cpp cfe/trunk/lib/Sema/SemaDeclAttr.cpp Modified: cfe/trunk/include/clang/AST/Decl.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Decl.h?rev=207734&r1=207733&r2=207734&view=diff ============================================================================== --- cfe/trunk/include/clang/AST/Decl.h (original) +++ cfe/trunk/include/clang/AST/Decl.h Wed Apr 30 22:16:47 2014 @@ -808,22 +808,12 @@ public: void setTSCSpec(ThreadStorageClassSpecifier TSC) { VarDeclBits.TSCSpec = TSC; + assert(VarDeclBits.TSCSpec == TSC && "truncation"); } ThreadStorageClassSpecifier getTSCSpec() const { return static_cast<ThreadStorageClassSpecifier>(VarDeclBits.TSCSpec); } - TLSKind getTLSKind() const { - switch (VarDeclBits.TSCSpec) { - case TSCS_unspecified: - return TLS_None; - case TSCS___thread: // Fall through. - case TSCS__Thread_local: - return TLS_Static; - case TSCS_thread_local: - return TLS_Dynamic; - } - llvm_unreachable("Unknown thread storage class specifier!"); - } + TLSKind getTLSKind() const; /// hasLocalStorage - Returns true if a variable with function scope /// is a non-static local variable. Modified: cfe/trunk/include/clang/Basic/Attr.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Attr.td?rev=207734&r1=207733&r2=207734&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/Attr.td (original) +++ cfe/trunk/include/clang/Basic/Attr.td Wed Apr 30 22:16:47 2014 @@ -1665,6 +1665,13 @@ def SelectAny : InheritableAttr { let Documentation = [Undocumented]; } +def Thread : Attr { + let Spellings = [Declspec<"thread">]; + let LangOpts = [MicrosoftExt]; + let Documentation = [ThreadDocs]; + let Subjects = SubjectList<[Var]>; +} + def Win64 : IgnoredAttr { let Spellings = [Keyword<"__w64">]; let LangOpts = [MicrosoftExt]; Modified: cfe/trunk/include/clang/Basic/AttrDocs.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/AttrDocs.td?rev=207734&r1=207733&r2=207734&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/AttrDocs.td (original) +++ cfe/trunk/include/clang/Basic/AttrDocs.td Wed Apr 30 22:16:47 2014 @@ -50,6 +50,23 @@ TLS models are mutually exclusive. }]; } +def ThreadDocs : Documentation { + let Category = DocCatVariable; + let Content = [{ +The ``__declspec(thread)`` attribute declares a variable with thread local +storage. It is available under the ``-fms-extensions`` flag for MSVC +compatibility. Documentation for the Visual C++ attribute is available on MSDN_. + +.. _MSDN: http://msdn.microsoft.com/en-us/library/9w1sdazb.aspx + +In Clang, ``__declspec(thread)`` is generally equivalent in functionality to the +GNU ``__thread`` keyword. The variable must not have a destructor and must have +a constant initializer, if any. The attribute only applies to variables +declared with static storage duration, such as globals, class static data +members, and static locals. + }]; +} + def CarriesDependencyDocs : Documentation { let Category = DocCatFunction; let Content = [{ Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=207734&r1=207733&r2=207734&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original) +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Wed Apr 30 22:16:47 2014 @@ -2081,6 +2081,9 @@ def err_attribute_weak_static : Error< "weak declaration cannot have internal linkage">; def err_attribute_selectany_non_extern_data : Error< "'selectany' can only be applied to data items with external linkage">; +def err_declspec_thread_on_thread_variable : Error< + "'__declspec(thread)' applied to variable that already has a " + "thread-local storage specifier">; def err_attribute_dll_not_extern : Error< "%q0 must have external linkage when declared %q1">; def warn_attribute_invalid_on_definition : Warning< @@ -5996,6 +5999,8 @@ def err_thread_dynamic_init : Error< "initializer for thread-local variable must be a constant expression">; def err_thread_nontrivial_dtor : Error< "type of thread-local variable has non-trivial destruction">; +def err_thread_nontrivial_ctor : Error< + "type of thread-local variable has non-trivial construction">; def note_use_thread_local : Note< "use 'thread_local' to allow this">; Modified: cfe/trunk/lib/AST/Decl.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Decl.cpp?rev=207734&r1=207733&r2=207734&view=diff ============================================================================== --- cfe/trunk/lib/AST/Decl.cpp (original) +++ cfe/trunk/lib/AST/Decl.cpp Wed Apr 30 22:16:47 2014 @@ -1646,6 +1646,21 @@ void VarDecl::setStorageClass(StorageCla VarDeclBits.SClass = SC; } +VarDecl::TLSKind VarDecl::getTLSKind() const { + switch (VarDeclBits.TSCSpec) { + case TSCS_unspecified: + if (hasAttr<ThreadAttr>()) + return TLS_Static; + return TLS_None; + case TSCS___thread: // Fall through. + case TSCS__Thread_local: + return TLS_Static; + case TSCS_thread_local: + return TLS_Dynamic; + } + llvm_unreachable("Unknown thread storage class specifier!"); +} + SourceRange VarDecl::getSourceRange() const { if (const Expr *Init = getInit()) { SourceLocation InitEnd = Init->getLocEnd(); Modified: cfe/trunk/lib/Sema/SemaDeclAttr.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclAttr.cpp?rev=207734&r1=207733&r2=207734&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaDeclAttr.cpp (original) +++ cfe/trunk/lib/Sema/SemaDeclAttr.cpp Wed Apr 30 22:16:47 2014 @@ -3697,6 +3697,25 @@ static void handleMSInheritanceAttr(Sema D->addAttr(IA); } +static void handleDeclspecThreadAttr(Sema &S, Decl *D, + const AttributeList &Attr) { + VarDecl *VD = cast<VarDecl>(D); + if (!S.Context.getTargetInfo().isTLSSupported()) { + S.Diag(Attr.getLoc(), diag::err_thread_unsupported); + return; + } + if (VD->getTSCSpec() != TSCS_unspecified) { + S.Diag(Attr.getLoc(), diag::err_declspec_thread_on_thread_variable); + return; + } + if (VD->hasLocalStorage()) { + S.Diag(Attr.getLoc(), diag::err_thread_non_global) << "__declspec(thread)"; + return; + } + VD->addAttr(::new (S.Context) ThreadAttr( + Attr.getRange(), S.Context, Attr.getAttributeSpellingListIndex())); +} + static void handleARMInterruptAttr(Sema &S, Decl *D, const AttributeList &Attr) { // Check the attribute arguments. @@ -4394,6 +4413,9 @@ static void ProcessDeclAttribute(Sema &S case AttributeList::AT_SelectAny: handleSimpleAttribute<SelectAnyAttr>(S, D, Attr); break; + case AttributeList::AT_Thread: + handleDeclspecThreadAttr(S, D, Attr); + break; // Thread safety attributes: case AttributeList::AT_AssertExclusiveLock: Added: cfe/trunk/test/SemaCXX/declspec-thread.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/declspec-thread.cpp?rev=207734&view=auto ============================================================================== --- cfe/trunk/test/SemaCXX/declspec-thread.cpp (added) +++ cfe/trunk/test/SemaCXX/declspec-thread.cpp Wed Apr 30 22:16:47 2014 @@ -0,0 +1,42 @@ +// RUN: %clang_cc1 -std=c++11 -fms-extensions -verify %s + +__thread __declspec(thread) int a; // expected-error {{already has a thread-local storage specifier}} +__declspec(thread) __thread int b; // expected-error {{already has a thread-local storage specifier}} +__declspec(thread) int c(); // expected-warning {{only applies to variables}} +__declspec(thread) int d; +int foo(); +__declspec(thread) int e = foo(); // expected-error {{must be a constant expression}} expected-note {{thread_local}} + +struct HasCtor { HasCtor(); int x; }; +__declspec(thread) HasCtor f; // expected-error {{must be a constant expression}} expected-note {{thread_local}} + +struct HasDtor { ~HasDtor(); int x; }; +__declspec(thread) HasDtor g; // expected-error {{non-trivial destruction}} expected-note {{thread_local}} + +struct HasDefaultedDefaultCtor { + HasDefaultedDefaultCtor() = default; + int x; +}; +__declspec(thread) HasDefaultedDefaultCtor h; + +struct HasConstexprCtor { + constexpr HasConstexprCtor(int x) : x(x) {} + int x; +}; +__declspec(thread) HasConstexprCtor i(42); + +int foo() { + __declspec(thread) int a; // expected-error {{must have global storage}} + static __declspec(thread) int b; +} + +extern __declspec(thread) int fwd_thread_var; +__declspec(thread) int fwd_thread_var = 5; + +extern int fwd_thread_var_mismatch; // expected-note {{previous declaration}} +__declspec(thread) int fwd_thread_var_mismatch = 5; // expected-error-re {{thread-local {{.*}} follows non-thread-local}} + +extern __declspec(thread) int thread_mismatch_2; // expected-note {{previous declaration}} +int thread_mismatch_2 = 5; // expected-error-re {{non-thread-local {{.*}} follows thread-local}} + +typedef __declspec(thread) int tls_int_t; // expected-warning {{only applies to variables}} _______________________________________________ cfe-commits mailing list [email protected] http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
