[PATCH] D18953: [ms][dll] #26935 Defining a dllimport function should cause it to be exported

2017-10-17 Thread Nico Weber via Phabricator via cfe-commits
thakis added inline comments.



Comment at: cfe/trunk/lib/Sema/SemaDecl.cpp:5650
+  NewImportAttr->getRange(), S.Context,
+  NewImportAttr->getSpellingListIndex()));
+} else {

NewImportAttr can be nullptr here, at least for invalid code. This change 
introduced https://bugs.llvm.org/show_bug.cgi?id=34981 , please take a look.


Repository:
  rL LLVM

https://reviews.llvm.org/D18953



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D18953: [ms][dll] #26935 Defining a dllimport function should cause it to be exported

2016-05-25 Thread Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL270686: [ms][dll] #26935 Defining a dllimport function 
should cause it to be exported (authored by dzobnin).

Changed prior to commit:
  http://reviews.llvm.org/D18953?vs=58233&id=58401#toc

Repository:
  rL LLVM

http://reviews.llvm.org/D18953

Files:
  cfe/trunk/include/clang/Basic/DiagnosticGroups.td
  cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
  cfe/trunk/lib/Sema/SemaDecl.cpp
  cfe/trunk/test/CodeGen/dllimport.c
  cfe/trunk/test/CodeGenCXX/dllimport-members.cpp
  cfe/trunk/test/CodeGenCXX/dllimport.cpp
  cfe/trunk/test/Sema/dllimport.c
  cfe/trunk/test/SemaCXX/dllimport.cpp

Index: cfe/trunk/test/SemaCXX/dllimport.cpp
===
--- cfe/trunk/test/SemaCXX/dllimport.cpp
+++ cfe/trunk/test/SemaCXX/dllimport.cpp
@@ -44,17 +44,49 @@
 int __declspec(dllimport) GlobalInit2 = 1; // expected-error{{definition of dllimport data}}
 
 // Declare, then reject definition.
-__declspec(dllimport) extern int ExternGlobalDeclInit; // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}}
-int ExternGlobalDeclInit = 1; // expected-warning{{'ExternGlobalDeclInit' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
+#ifdef GNU
+// expected-note@+2{{previous attribute is here}}
+#endif
+__declspec(dllimport) extern int ExternGlobalDeclInit; // expected-note{{previous declaration is here}}
+#ifdef MS
+// expected-warning@+4{{'ExternGlobalDeclInit' redeclared without 'dllimport' attribute: 'dllexport' attribute added}}
+#else
+// expected-warning@+2{{'ExternGlobalDeclInit' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
+#endif
+int ExternGlobalDeclInit = 1;
 
-__declspec(dllimport) int GlobalDeclInit; // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}}
-int GlobalDeclInit = 1; // expected-warning{{'GlobalDeclInit' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
+#ifdef GNU
+// expected-note@+2{{previous attribute is here}}
+#endif
+__declspec(dllimport) int GlobalDeclInit; // expected-note{{previous declaration is here}}
+#ifdef MS
+// expected-warning@+4{{'GlobalDeclInit' redeclared without 'dllimport' attribute: 'dllexport' attribute added}}
+#else
+// expected-warning@+2{{'GlobalDeclInit' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
+#endif
+int GlobalDeclInit = 1;
 
-int *__attribute__((dllimport)) GlobalDeclChunkAttrInit; // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}}
-int *GlobalDeclChunkAttrInit = 0; // expected-warning{{'GlobalDeclChunkAttrInit' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
+#ifdef GNU
+// expected-note@+2{{previous attribute is here}}
+#endif
+int *__attribute__((dllimport)) GlobalDeclChunkAttrInit; // expected-note{{previous declaration is here}}
+#ifdef MS
+// expected-warning@+4{{'GlobalDeclChunkAttrInit' redeclared without 'dllimport' attribute: 'dllexport' attribute added}}
+#else
+// expected-warning@+2{{'GlobalDeclChunkAttrInit' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
+#endif
+int *GlobalDeclChunkAttrInit = 0;
 
-int GlobalDeclAttrInit __attribute__((dllimport)); // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}}
-int GlobalDeclAttrInit = 1; // expected-warning{{'GlobalDeclAttrInit' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
+#ifdef GNU
+// expected-note@+2{{previous attribute is here}}
+#endif
+int GlobalDeclAttrInit __attribute__((dllimport)); // expected-note{{previous declaration is here}}
+#ifdef MS
+// expected-warning@+4{{'GlobalDeclAttrInit' redeclared without 'dllimport' attribute: 'dllexport' attribute added}}
+#else
+// expected-warning@+2{{'GlobalDeclAttrInit' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
+#endif
+int GlobalDeclAttrInit = 1;
 
 // Redeclarations
 __declspec(dllimport) extern int GlobalRedecl1;
@@ -69,8 +101,6 @@
 int GlobalRedecl2c __attribute__((dllimport));
 int GlobalRedecl2c __attribute__((dllimport));
 
-// NB: MSVC issues a warning and makes GlobalRedecl3 dllexport. We follow GCC
-// and drop the dllimport with a warning.
 __declspec(dllimport) extern int GlobalRedecl3; // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}}
   extern int GlobalRedecl3; // expected-warning{{'GlobalRedecl3' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
 
@@ -135,11 +165,31 @@
 template int __declspec(dllimport) VarTmplInit2 = 1; // expected-error{{definition of dllimport data}}
 
 // Declare, then reject definition.
-template __declspec(dllimport) extern int ExternVarTmplDeclInit; // expected-note{{previous declaration is here}} expected-note{{previous attribut

Re: [PATCH] D18953: [ms][dll] #26935 Defining a dllimport function should cause it to be exported

2016-05-24 Thread Reid Kleckner via cfe-commits
rnk added a comment.

lgtm


http://reviews.llvm.org/D18953



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D18953: [ms][dll] #26935 Defining a dllimport function should cause it to be exported

2016-05-24 Thread Andrew V. Tischenko via cfe-commits
avt77 updated this revision to Diff 58233.
avt77 added a comment.

I built the project from scratch and found an issue in Clang build system. 
There was a problem with undefined DiagGroup in DiagnosticSemaKinds.td: the 
error message was generated but all executables were created that's why I was 
not aware about this issue (I missed the message at the time of  my first build 
and all next re-builds worked without any problems). I created a new warning 
group (MicrosoftInconsistentDllImport) in DiagnosticGroups.td and made the 
corresponding changes in DiagnosticSemaKinds.td (2 lines).

Sorry for inconvenience but review the above two files and confirm your LGTM if 
it is.

And I suppose I should create a new record in Bugzilla, right?


http://reviews.llvm.org/D18953

Files:
  include/clang/Basic/DiagnosticGroups.td
  include/clang/Basic/DiagnosticSemaKinds.td
  lib/Sema/SemaDecl.cpp
  test/CodeGen/dllimport.c
  test/CodeGenCXX/dllimport-members.cpp
  test/CodeGenCXX/dllimport.cpp
  test/Sema/dllimport.c
  test/SemaCXX/dllimport.cpp

Index: lib/Sema/SemaDecl.cpp
===
--- lib/Sema/SemaDecl.cpp
+++ lib/Sema/SemaDecl.cpp
@@ -5523,9 +5523,13 @@
 
 static void checkDLLAttributeRedeclaration(Sema &S, NamedDecl *OldDecl,
NamedDecl *NewDecl,
-   bool IsSpecialization) {
-  if (TemplateDecl *OldTD = dyn_cast(OldDecl))
+   bool IsSpecialization,
+   bool IsDefinition) {
+  if (TemplateDecl *OldTD = dyn_cast(OldDecl)) {
 OldDecl = OldTD->getTemplatedDecl();
+if (!IsSpecialization)
+  IsDefinition = false;
+  }
   if (TemplateDecl *NewTD = dyn_cast(NewDecl))
 NewDecl = NewTD->getTemplatedDecl();
 
@@ -5581,30 +5585,43 @@
 
   // A redeclaration is not allowed to drop a dllimport attribute, the only
   // exceptions being inline function definitions, local extern declarations,
-  // and qualified friend declarations.
-  // NB: MSVC converts such a declaration to dllexport.
+  // qualified friend declarations or special MSVC extension: in the last case,
+  // the declaration is treated as if it were marked dllexport.
   bool IsInline = false, IsStaticDataMember = false, IsQualifiedFriend = false;
-  if (const auto *VD = dyn_cast(NewDecl))
+  bool IsMicrosoft = S.Context.getTargetInfo().getCXXABI().isMicrosoft();
+  if (const auto *VD = dyn_cast(NewDecl)) {
 // Ignore static data because out-of-line definitions are diagnosed
 // separately.
 IsStaticDataMember = VD->isStaticDataMember();
-  else if (const auto *FD = dyn_cast(NewDecl)) {
+IsDefinition = VD->isThisDeclarationADefinition(S.Context) !=
+   VarDecl::DeclarationOnly;
+  } else if (const auto *FD = dyn_cast(NewDecl)) {
 IsInline = FD->isInlined();
 IsQualifiedFriend = FD->getQualifier() &&
 FD->getFriendObjectKind() == Decl::FOK_Declared;
   }
 
   if (OldImportAttr && !HasNewAttr && !IsInline && !IsStaticDataMember &&
   !NewDecl->isLocalExternDecl() && !IsQualifiedFriend) {
-S.Diag(NewDecl->getLocation(),
-   diag::warn_redeclaration_without_attribute_prev_attribute_ignored)
-  << NewDecl << OldImportAttr;
-S.Diag(OldDecl->getLocation(), diag::note_previous_declaration);
-S.Diag(OldImportAttr->getLocation(), diag::note_previous_attribute);
-OldDecl->dropAttr();
-NewDecl->dropAttr();
-  } else if (IsInline && OldImportAttr &&
- !S.Context.getTargetInfo().getCXXABI().isMicrosoft()) {
+if (IsMicrosoft && IsDefinition) {
+  S.Diag(NewDecl->getLocation(),
+ diag::warn_redeclaration_without_import_attribute)
+  << NewDecl;
+  S.Diag(OldDecl->getLocation(), diag::note_previous_declaration);
+  NewDecl->dropAttr();
+  NewDecl->addAttr(::new (S.Context) DLLExportAttr(
+  NewImportAttr->getRange(), S.Context,
+  NewImportAttr->getSpellingListIndex()));
+} else {
+  S.Diag(NewDecl->getLocation(),
+ diag::warn_redeclaration_without_attribute_prev_attribute_ignored)
+  << NewDecl << OldImportAttr;
+  S.Diag(OldDecl->getLocation(), diag::note_previous_declaration);
+  S.Diag(OldImportAttr->getLocation(), diag::note_previous_attribute);
+  OldDecl->dropAttr();
+  NewDecl->dropAttr();
+}
+  } else if (IsInline && OldImportAttr && !IsMicrosoft) {
 // In MinGW, seeing a function declared inline drops the dllimport attribute.
 OldDecl->dropAttr();
 NewDecl->dropAttr();
@@ -6388,7 +6405,7 @@
   if (D.isRedeclaration() && !Previous.empty()) {
 checkDLLAttributeRedeclaration(
 *this, dyn_cast(Previous.getRepresentativeDecl()), NewVD,
-IsExplicitSpecialization);
+IsExplicitSpecialization, D.isFunctionDefinition());
   }
 
   if (NewTemplate) {
@@ -8419,7 +8436,8 @@
   if (D.isRedeclaration()

Re: [PATCH] D18953: [ms][dll] #26935 Defining a dllimport function should cause it to be exported

2016-05-23 Thread Reid Kleckner via cfe-commits
rnk accepted this revision.
rnk added a comment.
This revision is now accepted and ready to land.

lgtm


http://reviews.llvm.org/D18953



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D18953: [ms][dll] #26935 Defining a dllimport function should cause it to be exported

2016-05-23 Thread Andrew V. Tischenko via cfe-commits
avt77 added a comment.

OK, as I see all issues were resolved, right?
Could I commit the patch?


http://reviews.llvm.org/D18953



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D18953: [ms][dll] #26935 Defining a dllimport function should cause it to be exported

2016-05-13 Thread Reid Kleckner via cfe-commits
rnk added inline comments.


Comment at: test/SemaCXX/dllimport.cpp:179
@@ -140,1 +178,3 @@
+template 
+int ExternVarTmplDeclInit = 1;
 

avt77 wrote:
> majnemer wrote:
> > avt77 wrote:
> > > rnk wrote:
> > > > Can you check with MSVC 2015 update 2 actually does with definitions of 
> > > > dllimport variable templates? I bet it doesn't export them.
> > > They don't support variable templates at all:
> > > 
> > > error C2399: variable templates are not supported in this release
> > Your compiler is too old, they are definitely supported.
> > 
> > > Previously a template declaration was only allowed to be a function, 
> > > class, or alias. Now, in the MSVC compiler it can be a variable as well.
> > 
> > https://blogs.msdn.microsoft.com/vcblog/2016/02/11/compiler-improvements-in-vs-2015-update-2/
> OK, I updated several additional components and now CL supports variable 
> templates. I checked the issue again and got the following:
> 
> C:\_bugs>cl -c  t1.cpp
> Microsoft (R) C/C++ Optimizing Compiler Version 19.00.23918 for x86
> Copyright (C) Microsoft Corporation.  All rights reserved.
> 
> t1.cpp
> t1.cpp(8): warning C4273: 'ExternVarTmplDeclInit': inconsistent dll linkage
> t1.cpp(2): note: see previous definition of 'ExternVarTmplDeclInit'
> 
> C:\_bugs>dumpbin /directives t1.obj
> Microsoft (R) COFF/PE Dumper Version 14.00.23918.0
> Copyright (C) Microsoft Corporation.  All rights reserved.
> 
> 
> Dump of file t1.obj
> 
> File Type: COFF OBJECT
> 
>Linker Directives
>-
>/DEFAULTLIB:LIBCMT
>/DEFAULTLIB:OLDNAMES
>/EXPORT:??$ExternVarTmplDeclInit@H@@3HA,DATA//
> 
> As you see they produce warning and change the export attribute. I suppose 
> Clang should do the same, right?
Yep, sounds good for now.


Comment at: test/SemaCXX/dllimport.cpp:1137
@@ -1017,1 +1136,3 @@
+template 
+void ImportClassTmplMembers::normalDef() {}
 #ifdef GNU

avt77 wrote:
> avt77 wrote:
> > rnk wrote:
> > > I'm pretty sure MSVC considers all free function templates to be 
> > > 'inline', i.e. they put them in comdats. I doubt MSVC exports these. Can 
> > > you verify what it does?
> > They prohibit such a definition in the latest MSVC: 
> > 
> > error C2491: 'ImportClassTmplMembers::normalDef': definition of 
> > dllimport function not allowed
> > 
> > The same error I see for other definitions as well
> With the latest compiler they disallow the definition of dllimport functions 
> as well. I suppose Clang should do the same, right?
Seems like a weird special case. I wouldn't worry about addressing it right now.


http://reviews.llvm.org/D18953



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D18953: [ms][dll] #26935 Defining a dllimport function should cause it to be exported

2016-04-28 Thread Andrew V. Tischenko via cfe-commits
avt77 added inline comments.


Comment at: test/SemaCXX/dllimport.cpp:179
@@ -140,1 +178,3 @@
+template 
+int ExternVarTmplDeclInit = 1;
 

majnemer wrote:
> avt77 wrote:
> > rnk wrote:
> > > Can you check with MSVC 2015 update 2 actually does with definitions of 
> > > dllimport variable templates? I bet it doesn't export them.
> > They don't support variable templates at all:
> > 
> > error C2399: variable templates are not supported in this release
> Your compiler is too old, they are definitely supported.
> 
> > Previously a template declaration was only allowed to be a function, class, 
> > or alias. Now, in the MSVC compiler it can be a variable as well.
> 
> https://blogs.msdn.microsoft.com/vcblog/2016/02/11/compiler-improvements-in-vs-2015-update-2/
OK, I updated several additional components and now CL supports variable 
templates. I checked the issue again and got the following:

C:\_bugs>cl -c  t1.cpp
Microsoft (R) C/C++ Optimizing Compiler Version 19.00.23918 for x86
Copyright (C) Microsoft Corporation.  All rights reserved.

t1.cpp
t1.cpp(8): warning C4273: 'ExternVarTmplDeclInit': inconsistent dll linkage
t1.cpp(2): note: see previous definition of 'ExternVarTmplDeclInit'

C:\_bugs>dumpbin /directives t1.obj
Microsoft (R) COFF/PE Dumper Version 14.00.23918.0
Copyright (C) Microsoft Corporation.  All rights reserved.


Dump of file t1.obj

File Type: COFF OBJECT

   Linker Directives
   -
   /DEFAULTLIB:LIBCMT
   /DEFAULTLIB:OLDNAMES
   /EXPORT:??$ExternVarTmplDeclInit@H@@3HA,DATA//

As you see they produce warning and change the export attribute. I suppose 
Clang should do the same, right?


Comment at: test/SemaCXX/dllimport.cpp:1137
@@ -1017,1 +1136,3 @@
+template 
+void ImportClassTmplMembers::normalDef() {}
 #ifdef GNU

avt77 wrote:
> rnk wrote:
> > I'm pretty sure MSVC considers all free function templates to be 'inline', 
> > i.e. they put them in comdats. I doubt MSVC exports these. Can you verify 
> > what it does?
> They prohibit such a definition in the latest MSVC: 
> 
> error C2491: 'ImportClassTmplMembers::normalDef': definition of dllimport 
> function not allowed
> 
> The same error I see for other definitions as well
With the latest compiler they disallow the definition of dllimport functions as 
well. I suppose Clang should do the same, right?


http://reviews.llvm.org/D18953



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D18953: [ms][dll] #26935 Defining a dllimport function should cause it to be exported

2016-04-26 Thread David Majnemer via cfe-commits
majnemer added a subscriber: majnemer.


Comment at: test/SemaCXX/dllimport.cpp:179
@@ -140,1 +178,3 @@
+template 
+int ExternVarTmplDeclInit = 1;
 

avt77 wrote:
> rnk wrote:
> > Can you check with MSVC 2015 update 2 actually does with definitions of 
> > dllimport variable templates? I bet it doesn't export them.
> They don't support variable templates at all:
> 
> error C2399: variable templates are not supported in this release
Your compiler is too old, they are definitely supported.

> Previously a template declaration was only allowed to be a function, class, 
> or alias. Now, in the MSVC compiler it can be a variable as well.

https://blogs.msdn.microsoft.com/vcblog/2016/02/11/compiler-improvements-in-vs-2015-update-2/


http://reviews.llvm.org/D18953



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D18953: [ms][dll] #26935 Defining a dllimport function should cause it to be exported

2016-04-26 Thread Andrew V. Tischenko via cfe-commits
avt77 added a comment.

It seems the latest MSVC changed the support of several features covering in 
this patch: more investigations needed.



Comment at: test/SemaCXX/dllimport.cpp:179
@@ -140,1 +178,3 @@
+template 
+int ExternVarTmplDeclInit = 1;
 

rnk wrote:
> Can you check with MSVC 2015 update 2 actually does with definitions of 
> dllimport variable templates? I bet it doesn't export them.
They don't support variable templates at all:

error C2399: variable templates are not supported in this release


Comment at: test/SemaCXX/dllimport.cpp:1137
@@ -1017,1 +1136,3 @@
+template 
+void ImportClassTmplMembers::normalDef() {}
 #ifdef GNU

rnk wrote:
> I'm pretty sure MSVC considers all free function templates to be 'inline', 
> i.e. they put them in comdats. I doubt MSVC exports these. Can you verify 
> what it does?
They prohibit such a definition in the latest MSVC: 

error C2491: 'ImportClassTmplMembers::normalDef': definition of dllimport 
function not allowed

The same error I see for other definitions as well


http://reviews.llvm.org/D18953



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D18953: [ms][dll] #26935 Defining a dllimport function should cause it to be exported

2016-04-26 Thread Andrew V. Tischenko via cfe-commits
avt77 added a comment.

In fact you introduced the plan of actions to fix the issue. Tnx.


http://reviews.llvm.org/D18953



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D18953: [ms][dll] #26935 Defining a dllimport function should cause it to be exported

2016-04-20 Thread Richard Smith via cfe-commits
rsmith added a comment.

In http://reviews.llvm.org/D18953#397279, @rnk wrote:

> Richard, do you think we should be handling this by rewriting the AST-level 
> attribute in Sema or by changing our interpretation of things in CodeGen? 
> We're already creating a bunch of implicit attributes to implement 
> class-level import/export.


Sorry, I forgot to answer this directly. I'm fine with either approach; they 
both seem to preserve source fidelity and allow AST clients to figure out 
what's going on without too much complexity.


http://reviews.llvm.org/D18953



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D18953: [ms][dll] #26935 Defining a dllimport function should cause it to be exported

2016-04-20 Thread Reid Kleckner via cfe-commits
rnk added a comment.

I think this generally seems right, but we should make sure our behavior is 
more consistent in the case of a template definition.



Comment at: lib/Sema/SemaDecl.cpp:5570-5571
@@ -5565,4 +5569,4 @@
   // exceptions being inline function definitions, local extern declarations,
-  // and qualified friend declarations.
-  // NB: MSVC converts such a declaration to dllexport.
+  // qualified friend declarations or special MSVC extension: in the last case,
+  // the declaration is treated as if it were marked dllexport.
   bool IsInline = false, IsStaticDataMember = false, IsQualifiedFriend = false;

This comment is a run-on, maybe try this:

If a redeclaration drops the dllimport attribute, we usually ignore the 
previous attribute with a warning.
If the redeclaration is an inline definition, a local extern declaration, or a 
qualified friend declaration, we do nothing.
If this declaration is a plain, non-inline definition, then we translate 
dllimport to dllexport and warn the user.


Comment at: lib/Sema/SemaDecl.cpp:5595
@@ +5594,3 @@
+  NewDecl->addAttr(::new (S.Context) DLLExportAttr(
+  NewImportAttr->getRange(), S.Context,
+  NewImportAttr->getSpellingListIndex()));

In CodeGen, when we make decisions about the actual LLVM IR dll storage class, 
we should call Decl::getMostRecentDecl, and look at the attributes on that.

I think we can defer fixing this. You can see instances of the same problem 
below where we drop dllimport from previous declarations. We shouldn't be doing 
that.


Comment at: lib/Sema/SemaDecl.cpp:5600-5602
@@ +5599,5 @@
+ diag::warn_redeclaration_without_attribute_prev_attribute_ignored)
+  << NewDecl << OldImportAttr;
+  S.Diag(OldDecl->getLocation(), diag::note_previous_declaration);
+  S.Diag(OldImportAttr->getLocation(), diag::note_previous_attribute);
+  OldDecl->dropAttr();

Use DLLExportAttr::CreateImplicit or Attr->setImplicit(true).


Comment at: test/Sema/dllimport.c:52
@@ +51,3 @@
+__declspec(dllimport) int GlobalDeclInit; // expected-note{{previous 
declaration is here}}
+#ifdef MS
+// expected-warning@+4{{'GlobalDeclInit' redeclared without 'dllimport' 
attribute: 'dllexport' attribute added}}

We've already got one test for the difference between MSVC and GNU mode. I 
think the rest of these test cases can skip the ifdefs and look for the common 
prefix instead, like this:
  // expected-warning {{'GlobalDeclInit' redeclared without 'dllimport' 
attribute}}


Comment at: test/SemaCXX/dllimport.cpp:62
@@ +61,3 @@
+__declspec(dllimport) int GlobalDeclInit; // expected-note{{previous 
declaration is here}}
+#ifdef MS
+// expected-warning@+4{{'GlobalDeclInit' redeclared without 'dllimport' 
attribute: 'dllexport' attribute added}}

ditto, after the first MS-specific diagnostic test case we don't need the 
duplication


Comment at: test/SemaCXX/dllimport.cpp:179
@@ -140,1 +178,3 @@
+template 
+int ExternVarTmplDeclInit = 1;
 

Can you check with MSVC 2015 update 2 actually does with definitions of 
dllimport variable templates? I bet it doesn't export them.


Comment at: test/SemaCXX/dllimport.cpp:1137
@@ -1017,1 +1136,3 @@
+template 
+void ImportClassTmplMembers::normalDef() {}
 #ifdef GNU

I'm pretty sure MSVC considers all free function templates to be 'inline', i.e. 
they put them in comdats. I doubt MSVC exports these. Can you verify what it 
does?


http://reviews.llvm.org/D18953



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D18953: [ms][dll] #26935 Defining a dllimport function should cause it to be exported

2016-04-15 Thread Andrew V. Tischenko via cfe-commits
avt77 changed the visibility of this Differential Revision from "All Users" to 
"Public (No Login Required)".
avt77 updated this revision to Diff 53870.
avt77 added a comment.

I fixed all issues discovered by Richard and Reid. As result the tests were 
updated as well. Please, review again.


http://reviews.llvm.org/D18953

Files:
  include/clang/Basic/DiagnosticSemaKinds.td
  lib/Sema/SemaDecl.cpp
  test/CodeGen/dllimport.c
  test/CodeGenCXX/dllimport-members.cpp
  test/CodeGenCXX/dllimport.cpp
  test/Sema/dllimport.c
  test/SemaCXX/dllimport.cpp

Index: lib/Sema/SemaDecl.cpp
===
--- lib/Sema/SemaDecl.cpp
+++ lib/Sema/SemaDecl.cpp
@@ -5505,9 +5505,13 @@
 
 static void checkDLLAttributeRedeclaration(Sema &S, NamedDecl *OldDecl,
NamedDecl *NewDecl,
-   bool IsSpecialization) {
-  if (TemplateDecl *OldTD = dyn_cast(OldDecl))
+   bool IsSpecialization,
+   bool IsDefinition) {
+  if (TemplateDecl *OldTD = dyn_cast(OldDecl)) {
 OldDecl = OldTD->getTemplatedDecl();
+if (!IsSpecialization)
+  IsDefinition = false;
+  }
   if (TemplateDecl *NewTD = dyn_cast(NewDecl))
 NewDecl = NewTD->getTemplatedDecl();
 
@@ -5563,30 +5567,43 @@
 
   // A redeclaration is not allowed to drop a dllimport attribute, the only
   // exceptions being inline function definitions, local extern declarations,
-  // and qualified friend declarations.
-  // NB: MSVC converts such a declaration to dllexport.
+  // qualified friend declarations or special MSVC extension: in the last case,
+  // the declaration is treated as if it were marked dllexport.
   bool IsInline = false, IsStaticDataMember = false, IsQualifiedFriend = false;
-  if (const auto *VD = dyn_cast(NewDecl))
+  bool IsMicrosoft = S.Context.getTargetInfo().getCXXABI().isMicrosoft();
+  if (const auto *VD = dyn_cast(NewDecl)) {
 // Ignore static data because out-of-line definitions are diagnosed
 // separately.
 IsStaticDataMember = VD->isStaticDataMember();
-  else if (const auto *FD = dyn_cast(NewDecl)) {
+IsDefinition = !VD->isThisDeclarationADefinition(S.Context) ==
+   VarDecl::DeclarationOnly;
+  } else if (const auto *FD = dyn_cast(NewDecl)) {
 IsInline = FD->isInlined();
 IsQualifiedFriend = FD->getQualifier() &&
 FD->getFriendObjectKind() == Decl::FOK_Declared;
   }
 
   if (OldImportAttr && !HasNewAttr && !IsInline && !IsStaticDataMember &&
   !NewDecl->isLocalExternDecl() && !IsQualifiedFriend) {
-S.Diag(NewDecl->getLocation(),
-   diag::warn_redeclaration_without_attribute_prev_attribute_ignored)
-  << NewDecl << OldImportAttr;
-S.Diag(OldDecl->getLocation(), diag::note_previous_declaration);
-S.Diag(OldImportAttr->getLocation(), diag::note_previous_attribute);
-OldDecl->dropAttr();
-NewDecl->dropAttr();
-  } else if (IsInline && OldImportAttr &&
- !S.Context.getTargetInfo().getCXXABI().isMicrosoft()) {
+if (IsMicrosoft && IsDefinition) {
+  S.Diag(NewDecl->getLocation(),
+ diag::warn_redeclaration_without_import_attribute)
+  << NewDecl;
+  S.Diag(OldDecl->getLocation(), diag::note_previous_declaration);
+  NewDecl->dropAttr();
+  NewDecl->addAttr(::new (S.Context) DLLExportAttr(
+  NewImportAttr->getRange(), S.Context,
+  NewImportAttr->getSpellingListIndex()));
+} else {
+  S.Diag(NewDecl->getLocation(),
+ diag::warn_redeclaration_without_attribute_prev_attribute_ignored)
+  << NewDecl << OldImportAttr;
+  S.Diag(OldDecl->getLocation(), diag::note_previous_declaration);
+  S.Diag(OldImportAttr->getLocation(), diag::note_previous_attribute);
+  OldDecl->dropAttr();
+  NewDecl->dropAttr();
+}
+  } else if (IsInline && OldImportAttr && !IsMicrosoft) {
 // In MinGW, seeing a function declared inline drops the dllimport attribute.
 OldDecl->dropAttr();
 NewDecl->dropAttr();
@@ -6370,7 +6387,7 @@
   if (D.isRedeclaration() && !Previous.empty()) {
 checkDLLAttributeRedeclaration(
 *this, dyn_cast(Previous.getRepresentativeDecl()), NewVD,
-IsExplicitSpecialization);
+IsExplicitSpecialization, D.isFunctionDefinition());
   }
 
   if (NewTemplate) {
@@ -8369,7 +8386,8 @@
   if (D.isRedeclaration() && !Previous.empty()) {
 checkDLLAttributeRedeclaration(
 *this, dyn_cast(Previous.getRepresentativeDecl()), NewFD,
-isExplicitSpecialization || isFunctionTemplateSpecialization);
+isExplicitSpecialization || isFunctionTemplateSpecialization,
+D.isFunctionDefinition());
   }
 
   if (getLangOpts().CUDA) {
Index: include/clang/Basic/DiagnosticSemaKinds.td
===
--- include/clang/Basic/Diagnost

Re: [PATCH] D18953: [ms][dll] #26935 Defining a dllimport function should cause it to be exported

2016-04-12 Thread Andrew V. Tischenko via cfe-commits
avt77 marked an inline comment as done.


Comment at: lib/Sema/SemaDecl.cpp:5570
@@ -5565,3 +5569,3 @@
   // and qualified friend declarations.
-  // NB: MSVC converts such a declaration to dllexport.
+  // NB: MSVC converts such a declaration to dllexport that's why we do it 
also.
   bool IsInline = false, IsStaticDataMember = false, IsQualifiedFriend = false;

rsmith wrote:
> Just describe this as the semantics of this situation rather than suggesting 
> this is some MSVC oddity we're emulating. "In such a case, the declaration is 
> treated as if it were marked dllexport." or similar.
> 
> It also seems bizarre for this behavior to apply for local extern 
> declarations and qualified friend declarations. Does the "dllimport gets 
> turned into dllexport" behavior actually only apply to the definition case? 
> And does the definition need to be inline?
Yes, I see "dllimport gets turned into dllexport" for definitions only. 
No, the definition should not be inline: 
   if (OldImportAttr && !HasNewAttr && **!IsInline**


Comment at: lib/Sema/SemaDecl.cpp:5595
@@ +5594,3 @@
+  // Replace DLLImportAttr with DLLExportAttr
+  OldDecl->dropAttr();
+  NewDecl->dropAttr();

rsmith wrote:
> Don't change attributes on a prior declaration; AST nodes should generally be 
> immutable once created (this would lose source fidelity, and break under 
> PCH/modules). Instead, make sure that anyone who looks at this gets the 
> attribute from the appropriate (most recent) declaration and only change the 
> attributes there.
 I don't understand how I could "make sure that anyone...". Please, clarify. 


Comment at: lib/Sema/SemaDecl.cpp:5596
@@ +5595,3 @@
+  OldDecl->dropAttr();
+  NewDecl->dropAttr();
+  OldDecl->addAttr(::new (S.Context) DLLExportAttr(

rsmith wrote:
> Is this really valid and treated as `__dllexport` if the new declaration 
> explicitly specifies `__dllimport` (rather than inheriting it)?
The new declaration does not have explicitly specified __dllimport attribute: 
if (OldImportAttr && **!HasNewAttr**. It's inherited.


Comment at: lib/Sema/SemaDecl.cpp:5600-5602
@@ +5599,5 @@
+  OldImportAttr->getSpellingListIndex()));
+  NewDecl->addAttr(::new (S.Context) DLLExportAttr(
+  NewImportAttr->getRange(), S.Context,
+  NewImportAttr->getSpellingListIndex()));
+} else {

rsmith wrote:
> The new attribute should be marked implicit.
What do you mean? Please, clarify.


http://reviews.llvm.org/D18953



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D18953: [ms][dll] #26935 Defining a dllimport function should cause it to be exported

2016-04-11 Thread Richard Smith via cfe-commits
rsmith added inline comments.


Comment at: lib/Sema/SemaDecl.cpp:5570
@@ -5565,3 +5569,3 @@
   // and qualified friend declarations.
-  // NB: MSVC converts such a declaration to dllexport.
+  // NB: MSVC converts such a declaration to dllexport that's why we do it 
also.
   bool IsInline = false, IsStaticDataMember = false, IsQualifiedFriend = false;

Just describe this as the semantics of this situation rather than suggesting 
this is some MSVC oddity we're emulating. "In such a case, the declaration is 
treated as if it were marked dllexport." or similar.

It also seems bizarre for this behavior to apply for local extern declarations 
and qualified friend declarations. Does the "dllimport gets turned into 
dllexport" behavior actually only apply to the definition case? And does the 
definition need to be inline?


Comment at: lib/Sema/SemaDecl.cpp:5595
@@ +5594,3 @@
+  // Replace DLLImportAttr with DLLExportAttr
+  OldDecl->dropAttr();
+  NewDecl->dropAttr();

Don't change attributes on a prior declaration; AST nodes should generally be 
immutable once created (this would lose source fidelity, and break under 
PCH/modules). Instead, make sure that anyone who looks at this gets the 
attribute from the appropriate (most recent) declaration and only change the 
attributes there.


Comment at: lib/Sema/SemaDecl.cpp:5596
@@ +5595,3 @@
+  OldDecl->dropAttr();
+  NewDecl->dropAttr();
+  OldDecl->addAttr(::new (S.Context) DLLExportAttr(

Is this really valid and treated as `__dllexport` if the new declaration 
explicitly specifies `__dllimport` (rather than inheriting it)?


Comment at: lib/Sema/SemaDecl.cpp:5600-5602
@@ +5599,5 @@
+  OldImportAttr->getSpellingListIndex()));
+  NewDecl->addAttr(::new (S.Context) DLLExportAttr(
+  NewImportAttr->getRange(), S.Context,
+  NewImportAttr->getSpellingListIndex()));
+} else {

The new attribute should be marked implicit.


http://reviews.llvm.org/D18953



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D18953: [ms][dll] #26935 Defining a dllimport function should cause it to be exported

2016-04-11 Thread Reid Kleckner via cfe-commits
rnk added a comment.

Richard, do you think we should be handling this by rewriting the AST-level 
attribute in Sema or by changing our interpretation of things in CodeGen? We're 
already creating a bunch of implicit attributes to implement class-level 
import/export.



Comment at: lib/Sema/SemaDecl.cpp:5572
@@ -5567,2 +5571,3 @@
   bool IsInline = false, IsStaticDataMember = false, IsQualifiedFriend = false;
-  if (const auto *VD = dyn_cast(NewDecl))
+  bool isMicrosoft = S.Context.getTargetInfo().getCXXABI().isMicrosoft();
+  if (const auto *VD = dyn_cast(NewDecl)) {

To be consistent, this should be `IsMicrosoft`.


http://reviews.llvm.org/D18953



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D18953: [ms][dll] #26935 Defining a dllimport function should cause it to be exported

2016-04-11 Thread Andrew V. Tischenko via cfe-commits
avt77 created this revision.
avt77 added a reviewer: rnk.
avt77 added a subscriber: cfe-commits.
avt77 changed the visibility of this Differential Revision from "Public (No 
Login Required)" to "All Users".

If we have some function with dllimport attribute and then we have the function 
definition in the same module but without dllimport attribute we should add 
dllexport attribute to this function definition. The same should be done for 
variables. Example:

struct __declspec(dllimport) C3 {
   ~C3();
};

C3::~C3() {;} // we should export this definition

http://reviews.llvm.org/D18953

Files:
  include/clang/Basic/DiagnosticSemaKinds.td
  lib/Sema/SemaDecl.cpp
  test/CodeGen/dllimport.c
  test/CodeGenCXX/dllimport-members.cpp
  test/CodeGenCXX/dllimport.cpp
  test/Sema/dllimport.c
  test/SemaCXX/dllimport.cpp

Index: lib/Sema/SemaDecl.cpp
===
--- lib/Sema/SemaDecl.cpp
+++ lib/Sema/SemaDecl.cpp
@@ -5504,9 +5504,13 @@
 
 static void checkDLLAttributeRedeclaration(Sema &S, NamedDecl *OldDecl,
NamedDecl *NewDecl,
-   bool IsSpecialization) {
-  if (TemplateDecl *OldTD = dyn_cast(OldDecl))
+   bool IsSpecialization,
+   bool IsDefinition = false) {
+  if (TemplateDecl *OldTD = dyn_cast(OldDecl)) {
 OldDecl = OldTD->getTemplatedDecl();
+if (!IsSpecialization)
+  IsDefinition = false;
+  }
   if (TemplateDecl *NewTD = dyn_cast(NewDecl))
 NewDecl = NewTD->getTemplatedDecl();
 
@@ -5563,29 +5567,49 @@
   // A redeclaration is not allowed to drop a dllimport attribute, the only
   // exceptions being inline function definitions, local extern declarations,
   // and qualified friend declarations.
-  // NB: MSVC converts such a declaration to dllexport.
+  // NB: MSVC converts such a declaration to dllexport that's why we do it also.
   bool IsInline = false, IsStaticDataMember = false, IsQualifiedFriend = false;
-  if (const auto *VD = dyn_cast(NewDecl))
+  bool isMicrosoft = S.Context.getTargetInfo().getCXXABI().isMicrosoft();
+  if (const auto *VD = dyn_cast(NewDecl)) {
 // Ignore static data because out-of-line definitions are diagnosed
 // separately.
 IsStaticDataMember = VD->isStaticDataMember();
+IsDefinition =
+  !VD->isThisDeclarationADefinition(S.Context) == VarDecl::DeclarationOnly;
+  }
   else if (const auto *FD = dyn_cast(NewDecl)) {
 IsInline = FD->isInlined();
 IsQualifiedFriend = FD->getQualifier() &&
 FD->getFriendObjectKind() == Decl::FOK_Declared;
   }
 
   if (OldImportAttr && !HasNewAttr && !IsInline && !IsStaticDataMember &&
   !NewDecl->isLocalExternDecl() && !IsQualifiedFriend) {
-S.Diag(NewDecl->getLocation(),
-   diag::warn_redeclaration_without_attribute_prev_attribute_ignored)
-  << NewDecl << OldImportAttr;
-S.Diag(OldDecl->getLocation(), diag::note_previous_declaration);
-S.Diag(OldImportAttr->getLocation(), diag::note_previous_attribute);
-OldDecl->dropAttr();
-NewDecl->dropAttr();
-  } else if (IsInline && OldImportAttr &&
- !S.Context.getTargetInfo().getCXXABI().isMicrosoft()) {
+if (isMicrosoft && IsDefinition) {
+  S.Diag(NewDecl->getLocation(),
+ diag::warn_redeclaration_without_import_attribute) << NewDecl;
+  S.Diag(OldDecl->getLocation(), diag::note_previous_declaration);
+  S.Diag(OldImportAttr->getLocation(),
+ diag::note_previous_attribute_replaced);
+  // Replace DLLImportAttr with DLLExportAttr
+  OldDecl->dropAttr();
+  NewDecl->dropAttr();
+  OldDecl->addAttr(::new (S.Context) DLLExportAttr(
+  OldImportAttr->getRange(), S.Context,
+  OldImportAttr->getSpellingListIndex()));
+  NewDecl->addAttr(::new (S.Context) DLLExportAttr(
+  NewImportAttr->getRange(), S.Context,
+  NewImportAttr->getSpellingListIndex()));
+} else {
+  S.Diag(NewDecl->getLocation(),
+ diag::warn_redeclaration_without_attribute_prev_attribute_ignored)
+  << NewDecl << OldImportAttr;
+  S.Diag(OldDecl->getLocation(), diag::note_previous_declaration);
+  S.Diag(OldImportAttr->getLocation(), diag::note_previous_attribute);
+  OldDecl->dropAttr();
+  NewDecl->dropAttr();
+}
+  } else if (IsInline && OldImportAttr && !isMicrosoft) {
 // In MinGW, seeing a function declared inline drops the dllimport attribute.
 OldDecl->dropAttr();
 NewDecl->dropAttr();
@@ -6369,7 +6393,8 @@
   if (D.isRedeclaration() && !Previous.empty()) {
 checkDLLAttributeRedeclaration(
 *this, dyn_cast(Previous.getRepresentativeDecl()), NewVD,
-IsExplicitSpecialization);
+IsExplicitSpecialization,
+D.isFunctionDefinition());
   }
 
   if (NewTemplate) {
@@ -8368,7 +8393,8 @@
   if (D.isRedeclaration() && !Prev