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); _______________________________________________ cfe-commits mailing list [email protected] http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
