On 04/06/2014 01:10, Reid Kleckner wrote:



On Mon, Jun 2, 2014 at 8:40 PM, Alp Toker <[email protected] <mailto:[email protected]>> wrote:


    On 03/06/2014 05:37, Hans Wennborg wrote:

        Hi nrieck, rnk,


    ?


        This allows us to compile the following kind of code, which
        occurs in MSVC headers:

           template <typename> struct S {
             __declspec(dllimport) static int x;
           };
           template <typename T> int S<T>::x;


    Based on your description it sounds like this isn't ill-formed but
    the attribute is just ignored. Review inline...

        Please take a look.

        http://reviews.llvm.org/D3998

        Files:
           include/clang/Basic/DiagnosticSemaKinds.td
           lib/Sema/SemaDecl.cpp
           test/SemaCXX/dllimport.cpp

        D3998.10038.patch


        Index: include/clang/Basic/DiagnosticSemaKinds.td
        ===================================================================
        --- include/clang/Basic/DiagnosticSemaKinds.td
        +++ include/clang/Basic/DiagnosticSemaKinds.td
        @@ -2109,6 +2109,9 @@
            "definition of dllimport data">;
          def err_attribute_dllimport_static_field_definition : Error<
            "definition of dllimport static field not allowed">;
        +def warn_attribute_dllimport_static_field_definition : Warning<
        +  "definition of dllimport static field not allowed">,
        +  InGroup<DiagGroup<"dllimport-static-field-def">>;


    If that's the case, just make this a warning, or at most, a
    DefaultError warning (that will be ignored in system headers).


The non-template case should definitely remain an error.

What does MSVC do? Reject, accept or warn?

          def err_attribute_dll_member_of_dll_class : Error<
            "attribute %q0 cannot be applied to member of %q1 class">;
          def err_attribute_weakref_not_static : Error<
        Index: lib/Sema/SemaDecl.cpp
        ===================================================================
        --- lib/Sema/SemaDecl.cpp
        +++ lib/Sema/SemaDecl.cpp
        @@ -9061,10 +9061,17 @@
            if (const DLLImportAttr *IA = VD->getAttr<DLLImportAttr>()) {
              if (VD->isStaticDataMember() && VD->isOutOfLine() &&
                  VD->isThisDeclarationADefinition()) {
        +      // Definitions of dllimport class template static data
        members occurs
        +      // in MSVC header files. Downgrade to a warning.
        +      bool JustWarn =
        cast<CXXRecordDecl>(VD->getFirstDecl()->getDeclContext())
        +  ->getDescribedClassTemplate();
        +


    There is no need for that check and it doesn't look right.


The way I think about these definitions of static data members of not-fully-specialized class templates is that they're like inline functions. I don't see any reason why you can't provide a definition out of line while still importing the definition from another DLL. It should get available_externally linkage. If it's not const, it's not very useful for optimization purposes, but it seems semantically consistent.

If it's perfectly OK and semantically consistent to accept this then why emit a warning?


What about the check do you think is wrong?

We'd normally check linkage/inlining or use some other existing predicate for a check like this instead of poking at the decl for a specific special case.

Also note the patch was described as a system header workaround, while you're talking about accepting it as fully valid user code. The correct way to implement this patch depends on which of the two is preferable -- so that needs to be decided on first.

Alp.

The one case I'd want to make sure we still error on is the out-of-line definition of a static data member of a fully-specialized class template:
template <typename T> struct S { static int x; };
template <typename T> int S<T>::x = sizeof(T);
template <> struct __declspec(dllimport) S<int> { static int x; };
int S<int>::x = -1; // should error, only the dll should have this definition.

                Diag(VD->getLocation(),
- diag::err_attribute_dllimport_static_field_definition);
        +           JustWarn ?
        diag::warn_attribute_dllimport_static_field_definition
        +                    :
        diag::err_attribute_dllimport_static_field_definition);
                Diag(IA->getLocation(), diag::note_attribute);
        -      VD->setInvalidDecl();
        +      if (!JustWarn)
        +        VD->setInvalidDecl();


    Assuming the code isn't ill-formed, the declaration should not be
    set invalid at all.

    Alp.

              }
            }
          Index: test/SemaCXX/dllimport.cpp
        ===================================================================
        --- test/SemaCXX/dllimport.cpp
        +++ test/SemaCXX/dllimport.cpp
        @@ -816,9 +816,9 @@
          template<typename T> inline void
        ImportClassTmplMembers<T>::staticInlineDef() {}
          template<typename T>        void
        ImportClassTmplMembers<T>::staticInlineDecl() {}
          -template<typename T>        int
         ImportClassTmplMembers<T>::StaticFieldDef; //
        expected-error{{definition of dllimport static field not allowed}}
        -template<typename T> const  int
         ImportClassTmplMembers<T>::StaticConstFieldDef = 1; //
        expected-error{{definition of dllimport static field not allowed}}
        -template<typename T> constexpr int
        ImportClassTmplMembers<T>::ConstexprFieldDef; //
        expected-error{{definition of dllimport static field not allowed}}
        +template<typename T>        int
         ImportClassTmplMembers<T>::StaticFieldDef; //
        expected-warning{{definition of dllimport static field not
        allowed}}
        +template<typename T> const  int
         ImportClassTmplMembers<T>::StaticConstFieldDef = 1; //
        expected-warning{{definition of dllimport static field not
        allowed}}
        +template<typename T> constexpr int
        ImportClassTmplMembers<T>::ConstexprFieldDef; //
        expected-warning{{definition of dllimport static field not
        allowed}}
              // Redeclarations cannot add dllimport.
        @@ -853,13 +853,13 @@
          template<typename T> __declspec(dllimport)  void
        CTMR<T>::staticInlineDecl() {}  //
        expected-error{{redeclaration of 'CTMR::staticInlineDecl'
        cannot add 'dllimport' attribute}}
            template<typename T> __declspec(dllimport)    int
         CTMR<T>::StaticField = 1;       //
        expected-error{{redeclaration of 'CTMR::StaticField' cannot
        add 'dllimport' attribute}}
        -                                 //
        expected-error@-1{{definition of dllimport static field not
        allowed}}
        +                                 //
        expected-warning@-1{{definition of dllimport static field not
        allowed}}
                                         //
        expected-note@-2{{attribute is here}}
          template<typename T> __declspec(dllimport) const  int
         CTMR<T>::StaticConstField = 1;  //
        expected-error{{redeclaration of 'CTMR::StaticConstField'
        cannot add 'dllimport' attribute}}
        -                                 //
        expected-error@-1{{definition of dllimport static field not
        allowed}}
        +                                 //
        expected-warning@-1{{definition of dllimport static field not
        allowed}}
                                         //
        expected-note@-2{{attribute is here}}
          template<typename T> __declspec(dllimport) constexpr int
        CTMR<T>::ConstexprField;      // expected-error{{redeclaration
        of 'CTMR::ConstexprField' cannot add 'dllimport' attribute}}
        -                                 //
        expected-error@-1{{definition of dllimport static field not
        allowed}}
        +                                 //
        expected-warning@-1{{definition of dllimport static field not
        allowed}}
                                         //
        expected-note@-2{{attribute is here}}
            @@ -901,9 +901,9 @@
          template<typename T> template<typename U>        void
        ImportClsTmplMemTmpl<T>::staticInlineDecl() {}
            #if __has_feature(cxx_variable_templates)
        -template<typename T> template<typename U>      int
         ImportClsTmplMemTmpl<T>::StaticFieldDef; //
        expected-error{{definition of dllimport static field not allowed}}
        -template<typename T> template<typename U> const  int
         ImportClsTmplMemTmpl<T>::StaticConstFieldDef = 1; //
        expected-error{{definition of dllimport static field not allowed}}
        -template<typename T> template<typename U> constexpr int
        ImportClsTmplMemTmpl<T>::ConstexprFieldDef; //
        expected-error{{definition of dllimport static field not allowed}}
        +template<typename T> template<typename U>      int
         ImportClsTmplMemTmpl<T>::StaticFieldDef; //
        expected-warning{{definition of dllimport static field not
        allowed}}
        +template<typename T> template<typename U> const  int
         ImportClsTmplMemTmpl<T>::StaticConstFieldDef = 1; //
        expected-warning{{definition of dllimport static field not
        allowed}}
        +template<typename T> template<typename U> constexpr int
        ImportClsTmplMemTmpl<T>::ConstexprFieldDef; //
        expected-warning{{definition of dllimport static field not
        allowed}}
          #endif // __has_feature(cxx_variable_templates)
            @@ -935,13 +935,13 @@
            #if __has_feature(cxx_variable_templates)
          template<typename T> template<typename U>
__declspec(dllimport) int CTMTR<T>::StaticField = 1; // expected-error{{redeclaration of 'CTMTR::StaticField'
        cannot add 'dllimport' attribute}}
        -                                                       //
        expected-error@-1{{definition of dllimport static field not
        allowed}}
        +                                                       //
        expected-warning@-1{{definition of dllimport static field not
        allowed}}
         // expected-note@-2{{attribute is here}}
          template<typename T> template<typename U>
        __declspec(dllimport) const  int  CTMTR<T>::StaticConstField =
        1;  // expected-error{{redeclaration of
        'CTMTR::StaticConstField' cannot add 'dllimport' attribute}}
        -                                                       //
        expected-error@-1{{definition of dllimport static field not
        allowed}}
        +                                                       //
        expected-warning@-1{{definition of dllimport static field not
        allowed}}
         // expected-note@-2{{attribute is here}}
          template<typename T> template<typename U>
        __declspec(dllimport) constexpr int CTMTR<T>::ConstexprField;
             // expected-error{{redeclaration of
        'CTMTR::ConstexprField' cannot add 'dllimport' attribute}}
        -                                                       //
        expected-error@-1{{definition of dllimport static field not
        allowed}}
        +                                                       //
        expected-warning@-1{{definition of dllimport static field not
        allowed}}
         // expected-note@-2{{attribute is here}}
          #endif // __has_feature(cxx_variable_templates)


        _______________________________________________
        cfe-commits mailing list
        [email protected] <mailto:[email protected]>
        http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits


-- http://www.nuanti.com
    the browser experts



--
http://www.nuanti.com
the browser experts

_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to