r214774 - Don't drop dllimport from qualified friend redeclarations (PR20512)

Hans Wennborg hans at hanshq.net
Mon Aug 4 13:54:39 PDT 2014


Author: hans
Date: Mon Aug  4 15:54:39 2014
New Revision: 214774

URL: http://llvm.org/viewvc/llvm-project?rev=214774&view=rev
Log:
Don't drop dllimport from qualified friend redeclarations (PR20512)

This matches MSVC's logic, which seems to be that when the friend
declaration is qualified, it cannot be a declaration of a new symbol
and so the dll linkage doesn't change.

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

Modified:
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/test/CodeGenCXX/dllimport.cpp
    cfe/trunk/test/SemaCXX/dllimport.cpp

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=214774&r1=214773&r2=214774&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Mon Aug  4 15:54:39 2014
@@ -5047,18 +5047,22 @@ static void checkDLLAttributeRedeclarati
   }
 
   // A redeclaration is not allowed to drop a dllimport attribute, the only
-  // exceptions being inline function definitions and local extern declarations.
+  // exceptions being inline function definitions, local extern declarations,
+  // and qualified friend declarations.
   // NB: MSVC converts such a declaration to dllexport.
-  bool IsInline = false, IsStaticDataMember = false;
+  bool IsInline = false, IsStaticDataMember = false, IsQualifiedFriend = false;
   if (const auto *VD = dyn_cast<VarDecl>(NewDecl))
     // Ignore static data because out-of-line definitions are diagnosed
     // separately.
     IsStaticDataMember = VD->isStaticDataMember();
-  else if (const auto *FD = dyn_cast<FunctionDecl>(NewDecl))
+  else if (const auto *FD = dyn_cast<FunctionDecl>(NewDecl)) {
     IsInline = FD->isInlined();
+    IsQualifiedFriend = FD->getQualifier() &&
+                        FD->getFriendObjectKind() == Decl::FOK_Declared;
+  }
 
   if (OldImportAttr && !HasNewAttr && !IsInline && !IsStaticDataMember &&
-      !NewDecl->isLocalExternDecl()) {
+      !NewDecl->isLocalExternDecl() && !IsQualifiedFriend) {
     S.Diag(NewDecl->getLocation(),
            diag::warn_redeclaration_without_attribute_prev_attribute_ignored)
       << NewDecl << OldImportAttr;

Modified: cfe/trunk/test/CodeGenCXX/dllimport.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/dllimport.cpp?rev=214774&r1=214773&r2=214774&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/dllimport.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/dllimport.cpp Mon Aug  4 15:54:39 2014
@@ -276,6 +276,11 @@ USE(redecl3)
 // GNU-DAG: declare           void @_Z7friend2v()
 // MSC-DAG: define            void @"\01?friend3@@YAXXZ"()
 // GNU-DAG: define            void @_Z7friend3v()
+// MSC-DAG: declare           void @"\01?friend4@@YAXXZ"()
+// GNU-DAG: declare           void @_Z7friend4v()
+// MSC-DAG: declare dllimport void @"\01?friend5@@YAXXZ"()
+// GNU-DAG: declare dllimport void @_Z7friend5v()
+
 struct FuncFriend {
   friend __declspec(dllimport) void friend1();
   friend __declspec(dllimport) void friend2();
@@ -284,9 +289,18 @@ struct FuncFriend {
 __declspec(dllimport) void friend1();
                       void friend2(); // dllimport ignored
                       void friend3() {} // dllimport ignored
+
+__declspec(dllimport) void friend4();
+__declspec(dllimport) void friend5();
+struct FuncFriendRedecl {
+  friend void friend4(); // dllimport ignored
+  friend void ::friend5();
+};
 USE(friend1)
 USE(friend2)
 USE(friend3)
+USE(friend4)
+USE(friend5)
 
 // Implicit declarations can be redeclared with dllimport.
 // MSC-DAG: declare dllimport noalias i8* @"\01??2@{{YAPAXI|YAPEAX_K}}@Z"(

Modified: cfe/trunk/test/SemaCXX/dllimport.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/dllimport.cpp?rev=214774&r1=214773&r2=214774&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/dllimport.cpp (original)
+++ cfe/trunk/test/SemaCXX/dllimport.cpp Mon Aug  4 15:54:39 2014
@@ -243,6 +243,13 @@ __declspec(dllimport) void friend1();
 __declspec(dllimport) void friend4(); // expected-error{{redeclaration of 'friend4' cannot add 'dllimport' attribute}}
 __declspec(dllimport) inline void friend5() {} // expected-error{{redeclaration of 'friend5' cannot add 'dllimport' attribute}}
 
+void __declspec(dllimport) friend6(); // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}}
+void __declspec(dllimport) friend7();
+struct FuncFriend2 {
+  friend void friend6(); // expected-warning{{'friend6' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
+  friend void ::friend7();
+};
+
 // Implicit declarations can be redeclared with dllimport.
 __declspec(dllimport) void* operator new(__SIZE_TYPE__ n);
 





More information about the cfe-commits mailing list