forked from OSchip/llvm-project
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 llvm-svn: 214774
This commit is contained in:
parent
2120ecfe08
commit
7c4851e3ad
|
@ -5047,18 +5047,22 @@ static void checkDLLAttributeRedeclaration(Sema &S, NamedDecl *OldDecl,
|
|||
}
|
||||
|
||||
// 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;
|
||||
|
|
|
@ -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"(
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in New Issue