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

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.

Patch by Andrew V. Tischenko

Differential revision: http://reviews.llvm.org/D18953

llvm-svn: 270686
This commit is contained in:
Denis Zobnin 2016-05-25 11:32:42 +00:00
parent 1bcf9847a4
commit eebc4af0ed
8 changed files with 288 additions and 91 deletions

View File

@ -772,6 +772,7 @@ def MicrosoftEnumValue : DiagGroup<"microsoft-enum-value">;
def MicrosoftDefaultArgRedefinition : def MicrosoftDefaultArgRedefinition :
DiagGroup<"microsoft-default-arg-redefinition">; DiagGroup<"microsoft-default-arg-redefinition">;
def MicrosoftTemplate : DiagGroup<"microsoft-template">; def MicrosoftTemplate : DiagGroup<"microsoft-template">;
def MicrosoftInconsistentDllImport : DiagGroup<"inconsistent-dllimport">;
def MicrosoftRedeclareStatic : DiagGroup<"microsoft-redeclare-static">; def MicrosoftRedeclareStatic : DiagGroup<"microsoft-redeclare-static">;
def MicrosoftEnumForwardReference : def MicrosoftEnumForwardReference :
DiagGroup<"microsoft-enum-forward-reference">; DiagGroup<"microsoft-enum-forward-reference">;
@ -798,7 +799,8 @@ def Microsoft : DiagGroup<"microsoft",
MicrosoftRedeclareStatic, MicrosoftEnumForwardReference, MicrosoftGoto, MicrosoftRedeclareStatic, MicrosoftEnumForwardReference, MicrosoftGoto,
MicrosoftFlexibleArray, MicrosoftExtraQualification, MicrosoftCast, MicrosoftFlexibleArray, MicrosoftExtraQualification, MicrosoftCast,
MicrosoftConstInit, MicrosoftVoidPseudoDtor, MicrosoftAnonTag, MicrosoftConstInit, MicrosoftVoidPseudoDtor, MicrosoftAnonTag,
MicrosoftCommentPaste, MicrosoftEndOfFile]>; MicrosoftCommentPaste, MicrosoftEndOfFile,
MicrosoftInconsistentDllImport]>;
def ClangClPch : DiagGroup<"clang-cl-pch">; def ClangClPch : DiagGroup<"clang-cl-pch">;

View File

@ -2359,7 +2359,10 @@ def err_attribute_aligned_too_great : Error<
"requested alignment must be %0 bytes or smaller">; "requested alignment must be %0 bytes or smaller">;
def warn_redeclaration_without_attribute_prev_attribute_ignored : Warning< def warn_redeclaration_without_attribute_prev_attribute_ignored : Warning<
"%q0 redeclared without %1 attribute: previous %1 ignored">, "%q0 redeclared without %1 attribute: previous %1 ignored">,
InGroup<DiagGroup<"inconsistent-dllimport">>; InGroup<MicrosoftInconsistentDllImport>;
def warn_redeclaration_without_import_attribute : Warning<
"%q0 redeclared without 'dllimport' attribute: 'dllexport' attribute added">,
InGroup<MicrosoftInconsistentDllImport>;
def warn_dllimport_dropped_from_inline_function : Warning< def warn_dllimport_dropped_from_inline_function : Warning<
"%q0 redeclared inline; %1 attribute ignored">, "%q0 redeclared inline; %1 attribute ignored">,
InGroup<IgnoredAttributes>; InGroup<IgnoredAttributes>;

View File

@ -5559,9 +5559,13 @@ static void checkAttributesAfterMerging(Sema &S, NamedDecl &ND) {
static void checkDLLAttributeRedeclaration(Sema &S, NamedDecl *OldDecl, static void checkDLLAttributeRedeclaration(Sema &S, NamedDecl *OldDecl,
NamedDecl *NewDecl, NamedDecl *NewDecl,
bool IsSpecialization) { bool IsSpecialization,
if (TemplateDecl *OldTD = dyn_cast<TemplateDecl>(OldDecl)) bool IsDefinition) {
if (TemplateDecl *OldTD = dyn_cast<TemplateDecl>(OldDecl)) {
OldDecl = OldTD->getTemplatedDecl(); OldDecl = OldTD->getTemplatedDecl();
if (!IsSpecialization)
IsDefinition = false;
}
if (TemplateDecl *NewTD = dyn_cast<TemplateDecl>(NewDecl)) if (TemplateDecl *NewTD = dyn_cast<TemplateDecl>(NewDecl))
NewDecl = NewTD->getTemplatedDecl(); NewDecl = NewTD->getTemplatedDecl();
@ -5617,14 +5621,17 @@ static void checkDLLAttributeRedeclaration(Sema &S, NamedDecl *OldDecl,
// A redeclaration is not allowed to drop a dllimport attribute, the only // A redeclaration is not allowed to drop a dllimport attribute, the only
// exceptions being inline function definitions, local extern declarations, // exceptions being inline function definitions, local extern declarations,
// and qualified friend declarations. // qualified friend declarations or special MSVC extension: in the last case,
// NB: MSVC converts such a declaration to dllexport. // the declaration is treated as if it were marked dllexport.
bool IsInline = false, IsStaticDataMember = false, IsQualifiedFriend = false; bool IsInline = false, IsStaticDataMember = false, IsQualifiedFriend = false;
if (const auto *VD = dyn_cast<VarDecl>(NewDecl)) bool IsMicrosoft = S.Context.getTargetInfo().getCXXABI().isMicrosoft();
if (const auto *VD = dyn_cast<VarDecl>(NewDecl)) {
// Ignore static data because out-of-line definitions are diagnosed // Ignore static data because out-of-line definitions are diagnosed
// separately. // separately.
IsStaticDataMember = VD->isStaticDataMember(); IsStaticDataMember = VD->isStaticDataMember();
else if (const auto *FD = dyn_cast<FunctionDecl>(NewDecl)) { IsDefinition = VD->isThisDeclarationADefinition(S.Context) !=
VarDecl::DeclarationOnly;
} else if (const auto *FD = dyn_cast<FunctionDecl>(NewDecl)) {
IsInline = FD->isInlined(); IsInline = FD->isInlined();
IsQualifiedFriend = FD->getQualifier() && IsQualifiedFriend = FD->getQualifier() &&
FD->getFriendObjectKind() == Decl::FOK_Declared; FD->getFriendObjectKind() == Decl::FOK_Declared;
@ -5632,15 +5639,25 @@ static void checkDLLAttributeRedeclaration(Sema &S, NamedDecl *OldDecl,
if (OldImportAttr && !HasNewAttr && !IsInline && !IsStaticDataMember && if (OldImportAttr && !HasNewAttr && !IsInline && !IsStaticDataMember &&
!NewDecl->isLocalExternDecl() && !IsQualifiedFriend) { !NewDecl->isLocalExternDecl() && !IsQualifiedFriend) {
S.Diag(NewDecl->getLocation(), if (IsMicrosoft && IsDefinition) {
diag::warn_redeclaration_without_attribute_prev_attribute_ignored) S.Diag(NewDecl->getLocation(),
<< NewDecl << OldImportAttr; diag::warn_redeclaration_without_import_attribute)
S.Diag(OldDecl->getLocation(), diag::note_previous_declaration); << NewDecl;
S.Diag(OldImportAttr->getLocation(), diag::note_previous_attribute); S.Diag(OldDecl->getLocation(), diag::note_previous_declaration);
OldDecl->dropAttr<DLLImportAttr>(); NewDecl->dropAttr<DLLImportAttr>();
NewDecl->dropAttr<DLLImportAttr>(); NewDecl->addAttr(::new (S.Context) DLLExportAttr(
} else if (IsInline && OldImportAttr && NewImportAttr->getRange(), S.Context,
!S.Context.getTargetInfo().getCXXABI().isMicrosoft()) { 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<DLLImportAttr>();
NewDecl->dropAttr<DLLImportAttr>();
}
} else if (IsInline && OldImportAttr && !IsMicrosoft) {
// In MinGW, seeing a function declared inline drops the dllimport attribute. // In MinGW, seeing a function declared inline drops the dllimport attribute.
OldDecl->dropAttr<DLLImportAttr>(); OldDecl->dropAttr<DLLImportAttr>();
NewDecl->dropAttr<DLLImportAttr>(); NewDecl->dropAttr<DLLImportAttr>();
@ -6424,7 +6441,7 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
if (D.isRedeclaration() && !Previous.empty()) { if (D.isRedeclaration() && !Previous.empty()) {
checkDLLAttributeRedeclaration( checkDLLAttributeRedeclaration(
*this, dyn_cast<NamedDecl>(Previous.getRepresentativeDecl()), NewVD, *this, dyn_cast<NamedDecl>(Previous.getRepresentativeDecl()), NewVD,
IsExplicitSpecialization); IsExplicitSpecialization, D.isFunctionDefinition());
} }
if (NewTemplate) { if (NewTemplate) {
@ -8455,7 +8472,8 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
if (D.isRedeclaration() && !Previous.empty()) { if (D.isRedeclaration() && !Previous.empty()) {
checkDLLAttributeRedeclaration( checkDLLAttributeRedeclaration(
*this, dyn_cast<NamedDecl>(Previous.getRepresentativeDecl()), NewFD, *this, dyn_cast<NamedDecl>(Previous.getRepresentativeDecl()), NewFD,
isExplicitSpecialization || isFunctionTemplateSpecialization); isExplicitSpecialization || isFunctionTemplateSpecialization,
D.isFunctionDefinition());
} }
if (getLangOpts().CUDA) { if (getLangOpts().CUDA) {

View File

@ -45,7 +45,8 @@ __declspec(dllimport) extern int GlobalRedecl3;
USEVAR(GlobalRedecl3) USEVAR(GlobalRedecl3)
// Make sure this works even if the decl has been used before it's defined (PR20792). // Make sure this works even if the decl has been used before it's defined (PR20792).
// CHECK: @GlobalRedecl4 = common global i32 // MS: @GlobalRedecl4 = common dllexport global i32
// GNU: @GlobalRedecl4 = common global i32
__declspec(dllimport) extern int GlobalRedecl4; __declspec(dllimport) extern int GlobalRedecl4;
USEVAR(GlobalRedecl4) USEVAR(GlobalRedecl4)
int GlobalRedecl4; // dllimport ignored int GlobalRedecl4; // dllimport ignored
@ -111,13 +112,15 @@ __declspec(dllimport) void redecl2(void);
void redecl2(void); void redecl2(void);
USE(redecl2) USE(redecl2)
// CHECK-DAG: define void @redecl3() // MS: define dllexport void @redecl3()
// GNU: define void @redecl3()
__declspec(dllimport) void redecl3(void); __declspec(dllimport) void redecl3(void);
void redecl3(void) {} // dllimport ignored void redecl3(void) {} // dllimport ignored
USE(redecl3) USE(redecl3)
// Make sure this works even if the decl is used before it's defined (PR20792). // Make sure this works even if the decl is used before it's defined (PR20792).
// CHECK-DAG: define void @redecl4() // MS: define dllexport void @redecl4()
// GNU: define void @redecl4()
__declspec(dllimport) void redecl4(void); __declspec(dllimport) void redecl4(void);
USE(redecl4) USE(redecl4)
void redecl4(void) {} // dllimport ignored void redecl4(void) {} // dllimport ignored

View File

@ -63,8 +63,8 @@ struct ForceNonTrivial {
struct ImportMembers { struct ImportMembers {
struct Nested; struct Nested;
// M32-DAG: define x86_thiscallcc void @"\01?normalDef@ImportMembers@@QAEXXZ"(%struct.ImportMembers* %this) // M32-DAG: define dllexport x86_thiscallcc void @"\01?normalDef@ImportMembers@@QAEXXZ"(%struct.ImportMembers* %this)
// M64-DAG: define void @"\01?normalDef@ImportMembers@@QEAAXXZ"(%struct.ImportMembers* %this) // M64-DAG: define dllexport void @"\01?normalDef@ImportMembers@@QEAAXXZ"(%struct.ImportMembers* %this)
// M32-DAG: declare dllimport x86_thiscallcc void @"\01?normalDecl@ImportMembers@@QAEXXZ"(%struct.ImportMembers*) // M32-DAG: declare dllimport x86_thiscallcc void @"\01?normalDecl@ImportMembers@@QAEXXZ"(%struct.ImportMembers*)
// M64-DAG: declare dllimport void @"\01?normalDecl@ImportMembers@@QEAAXXZ"(%struct.ImportMembers*) // M64-DAG: declare dllimport void @"\01?normalDecl@ImportMembers@@QEAAXXZ"(%struct.ImportMembers*)
// M32-DAG: declare dllimport x86_thiscallcc void @"\01?normalInclass@ImportMembers@@QAEXXZ"(%struct.ImportMembers*) // M32-DAG: declare dllimport x86_thiscallcc void @"\01?normalInclass@ImportMembers@@QAEXXZ"(%struct.ImportMembers*)
@ -95,8 +95,8 @@ struct ImportMembers {
__declspec(dllimport) void normalInlineDef(); __declspec(dllimport) void normalInlineDef();
__declspec(dllimport) inline void normalInlineDecl(); __declspec(dllimport) inline void normalInlineDecl();
// M32-DAG: define x86_thiscallcc void @"\01?virtualDef@ImportMembers@@UAEXXZ"(%struct.ImportMembers* %this) // M32-DAG: define dllexport x86_thiscallcc void @"\01?virtualDef@ImportMembers@@UAEXXZ"(%struct.ImportMembers* %this)
// M64-DAG: define void @"\01?virtualDef@ImportMembers@@UEAAXXZ"(%struct.ImportMembers* %this) // M64-DAG: define dllexport void @"\01?virtualDef@ImportMembers@@UEAAXXZ"(%struct.ImportMembers* %this)
// M32-DAG: declare dllimport x86_thiscallcc void @"\01?virtualDecl@ImportMembers@@UAEXXZ"(%struct.ImportMembers*) // M32-DAG: declare dllimport x86_thiscallcc void @"\01?virtualDecl@ImportMembers@@UAEXXZ"(%struct.ImportMembers*)
// M64-DAG: declare dllimport void @"\01?virtualDecl@ImportMembers@@UEAAXXZ"(%struct.ImportMembers*) // M64-DAG: declare dllimport void @"\01?virtualDecl@ImportMembers@@UEAAXXZ"(%struct.ImportMembers*)
// M32-DAG: declare dllimport x86_thiscallcc void @"\01?virtualInclass@ImportMembers@@UAEXXZ"(%struct.ImportMembers*) // M32-DAG: declare dllimport x86_thiscallcc void @"\01?virtualInclass@ImportMembers@@UAEXXZ"(%struct.ImportMembers*)
@ -127,7 +127,7 @@ struct ImportMembers {
__declspec(dllimport) virtual void virtualInlineDef(); __declspec(dllimport) virtual void virtualInlineDef();
__declspec(dllimport) virtual inline void virtualInlineDecl(); __declspec(dllimport) virtual inline void virtualInlineDecl();
// MSC-DAG: define void @"\01?staticDef@ImportMembers@@SAXXZ"() // MSC-DAG: define dllexport void @"\01?staticDef@ImportMembers@@SAXXZ"()
// MSC-DAG: declare dllimport void @"\01?staticDecl@ImportMembers@@SAXXZ"() // MSC-DAG: declare dllimport void @"\01?staticDecl@ImportMembers@@SAXXZ"()
// MSC-DAG: declare dllimport void @"\01?staticInclass@ImportMembers@@SAXXZ"() // MSC-DAG: declare dllimport void @"\01?staticInclass@ImportMembers@@SAXXZ"()
// MSC-DAG: declare dllimport void @"\01?staticInlineDef@ImportMembers@@SAXXZ"() // MSC-DAG: declare dllimport void @"\01?staticInlineDef@ImportMembers@@SAXXZ"()
@ -235,8 +235,8 @@ USEMV(ImportMembers, ConstexprField)
// Import individual members of a nested class. // Import individual members of a nested class.
struct ImportMembers::Nested { struct ImportMembers::Nested {
// M32-DAG: define x86_thiscallcc void @"\01?normalDef@Nested@ImportMembers@@QAEXXZ"(%"struct.ImportMembers::Nested"* %this) // M32-DAG: define dllexport x86_thiscallcc void @"\01?normalDef@Nested@ImportMembers@@QAEXXZ"(%"struct.ImportMembers::Nested"* %this)
// M64-DAG: define void @"\01?normalDef@Nested@ImportMembers@@QEAAXXZ"(%"struct.ImportMembers::Nested"* %this) // M64-DAG: define dllexport void @"\01?normalDef@Nested@ImportMembers@@QEAAXXZ"(%"struct.ImportMembers::Nested"* %this)
// M32-DAG: declare dllimport x86_thiscallcc void @"\01?normalDecl@Nested@ImportMembers@@QAEXXZ"(%"struct.ImportMembers::Nested"*) // M32-DAG: declare dllimport x86_thiscallcc void @"\01?normalDecl@Nested@ImportMembers@@QAEXXZ"(%"struct.ImportMembers::Nested"*)
// M64-DAG: declare dllimport void @"\01?normalDecl@Nested@ImportMembers@@QEAAXXZ"(%"struct.ImportMembers::Nested"*) // M64-DAG: declare dllimport void @"\01?normalDecl@Nested@ImportMembers@@QEAAXXZ"(%"struct.ImportMembers::Nested"*)
// M32-DAG: declare dllimport x86_thiscallcc void @"\01?normalInclass@Nested@ImportMembers@@QAEXXZ"(%"struct.ImportMembers::Nested"*) // M32-DAG: declare dllimport x86_thiscallcc void @"\01?normalInclass@Nested@ImportMembers@@QAEXXZ"(%"struct.ImportMembers::Nested"*)
@ -267,8 +267,8 @@ struct ImportMembers::Nested {
__declspec(dllimport) void normalInlineDef(); __declspec(dllimport) void normalInlineDef();
__declspec(dllimport) inline void normalInlineDecl(); __declspec(dllimport) inline void normalInlineDecl();
// M32-DAG: define x86_thiscallcc void @"\01?virtualDef@Nested@ImportMembers@@UAEXXZ"(%"struct.ImportMembers::Nested"* %this) // M32-DAG: define dllexport x86_thiscallcc void @"\01?virtualDef@Nested@ImportMembers@@UAEXXZ"(%"struct.ImportMembers::Nested"* %this)
// M64-DAG: define void @"\01?virtualDef@Nested@ImportMembers@@UEAAXXZ"(%"struct.ImportMembers::Nested"* %this) // M64-DAG: define dllexport void @"\01?virtualDef@Nested@ImportMembers@@UEAAXXZ"(%"struct.ImportMembers::Nested"* %this)
// M32-DAG: declare dllimport x86_thiscallcc void @"\01?virtualDecl@Nested@ImportMembers@@UAEXXZ"(%"struct.ImportMembers::Nested"*) // M32-DAG: declare dllimport x86_thiscallcc void @"\01?virtualDecl@Nested@ImportMembers@@UAEXXZ"(%"struct.ImportMembers::Nested"*)
// M64-DAG: declare dllimport void @"\01?virtualDecl@Nested@ImportMembers@@UEAAXXZ"(%"struct.ImportMembers::Nested"*) // M64-DAG: declare dllimport void @"\01?virtualDecl@Nested@ImportMembers@@UEAAXXZ"(%"struct.ImportMembers::Nested"*)
// M32-DAG: declare dllimport x86_thiscallcc void @"\01?virtualInclass@Nested@ImportMembers@@UAEXXZ"(%"struct.ImportMembers::Nested"*) // M32-DAG: declare dllimport x86_thiscallcc void @"\01?virtualInclass@Nested@ImportMembers@@UAEXXZ"(%"struct.ImportMembers::Nested"*)
@ -300,7 +300,7 @@ struct ImportMembers::Nested {
__declspec(dllimport) virtual void virtualInlineDef(); __declspec(dllimport) virtual void virtualInlineDef();
__declspec(dllimport) virtual inline void virtualInlineDecl(); __declspec(dllimport) virtual inline void virtualInlineDecl();
// MSC-DAG: define void @"\01?staticDef@Nested@ImportMembers@@SAXXZ"() // MSC-DAG: define dllexport void @"\01?staticDef@Nested@ImportMembers@@SAXXZ"()
// MSC-DAG: declare dllimport void @"\01?staticDecl@Nested@ImportMembers@@SAXXZ"() // MSC-DAG: declare dllimport void @"\01?staticDecl@Nested@ImportMembers@@SAXXZ"()
// MSC-DAG: declare dllimport void @"\01?staticInclass@Nested@ImportMembers@@SAXXZ"() // MSC-DAG: declare dllimport void @"\01?staticInclass@Nested@ImportMembers@@SAXXZ"()
// MSC-DAG: declare dllimport void @"\01?staticInlineDef@Nested@ImportMembers@@SAXXZ"() // MSC-DAG: declare dllimport void @"\01?staticInlineDef@Nested@ImportMembers@@SAXXZ"()
@ -595,16 +595,16 @@ inline ImportDefaultedDefs::ImportDefaultedDefs(const ImportDefaultedDefs&) = de
// G64-DAG: define linkonce_odr dereferenceable({{[0-9]+}}) %struct.ImportDefaultedDefs* @_ZN19ImportDefaultedDefsaSERKS_(%struct.ImportDefaultedDefs* %this, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}})) // G64-DAG: define linkonce_odr dereferenceable({{[0-9]+}}) %struct.ImportDefaultedDefs* @_ZN19ImportDefaultedDefsaSERKS_(%struct.ImportDefaultedDefs* %this, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}}))
inline ImportDefaultedDefs& ImportDefaultedDefs::operator=(const ImportDefaultedDefs&) = default; inline ImportDefaultedDefs& ImportDefaultedDefs::operator=(const ImportDefaultedDefs&) = default;
// M32-DAG: define x86_thiscallcc %struct.ImportDefaultedDefs* @"\01??0ImportDefaultedDefs@@QAE@$$QAU0@@Z"(%struct.ImportDefaultedDefs* returned %this, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}})) // M32-DAG: define dllexport x86_thiscallcc %struct.ImportDefaultedDefs* @"\01??0ImportDefaultedDefs@@QAE@$$QAU0@@Z"(%struct.ImportDefaultedDefs* returned %this, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}}))
// M64-DAG: define %struct.ImportDefaultedDefs* @"\01??0ImportDefaultedDefs@@QEAA@$$QEAU0@@Z"(%struct.ImportDefaultedDefs* returned %this, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}})) // M64-DAG: define dllexport %struct.ImportDefaultedDefs* @"\01??0ImportDefaultedDefs@@QEAA@$$QEAU0@@Z"(%struct.ImportDefaultedDefs* returned %this, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}}))
// G32-DAG: define x86_thiscallcc void @_ZN19ImportDefaultedDefsC1EOS_(%struct.ImportDefaultedDefs* %this, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}})) // G32-DAG: define x86_thiscallcc void @_ZN19ImportDefaultedDefsC1EOS_(%struct.ImportDefaultedDefs* %this, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}}))
// G64-DAG: define void @_ZN19ImportDefaultedDefsC1EOS_(%struct.ImportDefaultedDefs* %this, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}})) // G64-DAG: define void @_ZN19ImportDefaultedDefsC1EOS_(%struct.ImportDefaultedDefs* %this, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}}))
// G32-DAG: define x86_thiscallcc void @_ZN19ImportDefaultedDefsC2EOS_(%struct.ImportDefaultedDefs* %this, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}})) // G32-DAG: define x86_thiscallcc void @_ZN19ImportDefaultedDefsC2EOS_(%struct.ImportDefaultedDefs* %this, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}}))
// G64-DAG: define void @_ZN19ImportDefaultedDefsC2EOS_(%struct.ImportDefaultedDefs* %this, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}})) // G64-DAG: define void @_ZN19ImportDefaultedDefsC2EOS_(%struct.ImportDefaultedDefs* %this, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}}))
ImportDefaultedDefs::ImportDefaultedDefs(ImportDefaultedDefs&&) = default; // dllimport ignored ImportDefaultedDefs::ImportDefaultedDefs(ImportDefaultedDefs&&) = default; // dllimport ignored
// M32-DAG: define x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportDefaultedDefs* @"\01??4ImportDefaultedDefs@@QAEAAU0@$$QAU0@@Z"(%struct.ImportDefaultedDefs* %this, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}})) // M32-DAG: define dllexport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportDefaultedDefs* @"\01??4ImportDefaultedDefs@@QAEAAU0@$$QAU0@@Z"(%struct.ImportDefaultedDefs* %this, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}}))
// M64-DAG: define dereferenceable({{[0-9]+}}) %struct.ImportDefaultedDefs* @"\01??4ImportDefaultedDefs@@QEAAAEAU0@$$QEAU0@@Z"(%struct.ImportDefaultedDefs* %this, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}})) // M64-DAG: define dllexport dereferenceable({{[0-9]+}}) %struct.ImportDefaultedDefs* @"\01??4ImportDefaultedDefs@@QEAAAEAU0@$$QEAU0@@Z"(%struct.ImportDefaultedDefs* %this, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}}))
// G32-DAG: define x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportDefaultedDefs* @_ZN19ImportDefaultedDefsaSEOS_(%struct.ImportDefaultedDefs* %this, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}})) // G32-DAG: define x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportDefaultedDefs* @_ZN19ImportDefaultedDefsaSEOS_(%struct.ImportDefaultedDefs* %this, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}}))
// G64-DAG: define dereferenceable({{[0-9]+}}) %struct.ImportDefaultedDefs* @_ZN19ImportDefaultedDefsaSEOS_(%struct.ImportDefaultedDefs* %this, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}})) // G64-DAG: define dereferenceable({{[0-9]+}}) %struct.ImportDefaultedDefs* @_ZN19ImportDefaultedDefsaSEOS_(%struct.ImportDefaultedDefs* %this, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}}))
ImportDefaultedDefs& ImportDefaultedDefs::operator=(ImportDefaultedDefs&&) = default; // dllimport ignored ImportDefaultedDefs& ImportDefaultedDefs::operator=(ImportDefaultedDefs&&) = default; // dllimport ignored

View File

@ -264,7 +264,7 @@ __declspec(dllimport) void redecl2();
void redecl2(); void redecl2();
USE(redecl2) USE(redecl2)
// MSC-DAG: define void @"\01?redecl3@@YAXXZ"() // MSC-DAG: define dllexport void @"\01?redecl3@@YAXXZ"()
// GNU-DAG: define void @_Z7redecl3v() // GNU-DAG: define void @_Z7redecl3v()
__declspec(dllimport) void redecl3(); __declspec(dllimport) void redecl3();
void redecl3() {} // dllimport ignored void redecl3() {} // dllimport ignored
@ -276,7 +276,7 @@ USE(redecl3)
// GNU-DAG: declare dllimport void @_Z7friend1v() // GNU-DAG: declare dllimport void @_Z7friend1v()
// MSC-DAG: declare void @"\01?friend2@@YAXXZ"() // MSC-DAG: declare void @"\01?friend2@@YAXXZ"()
// GNU-DAG: declare void @_Z7friend2v() // GNU-DAG: declare void @_Z7friend2v()
// MSC-DAG: define void @"\01?friend3@@YAXXZ"() // MSC-DAG: define dllexport void @"\01?friend3@@YAXXZ"()
// GNU-DAG: define void @_Z7friend3v() // GNU-DAG: define void @_Z7friend3v()
// MSC-DAG: declare void @"\01?friend4@@YAXXZ"() // MSC-DAG: declare void @"\01?friend4@@YAXXZ"()
// GNU-DAG: declare void @_Z7friend4v() // GNU-DAG: declare void @_Z7friend4v()

View File

@ -34,17 +34,49 @@ __declspec(dllimport) int GlobalInit1 = 1; // expected-error{{definition of dlli
int __declspec(dllimport) GlobalInit2 = 1; // expected-error{{definition of dllimport data}} int __declspec(dllimport) GlobalInit2 = 1; // expected-error{{definition of dllimport data}}
// Declare, then reject definition. // Declare, then reject definition.
__declspec(dllimport) extern int ExternGlobalDeclInit; // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}} #ifdef GNU
int ExternGlobalDeclInit = 1; // expected-warning{{'ExternGlobalDeclInit' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} // 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}} #ifdef GNU
int GlobalDeclInit = 1; // expected-warning{{'GlobalDeclInit' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} // 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}} #ifdef GNU
int *GlobalDeclChunkAttrInit = 0; // expected-warning{{'GlobalDeclChunkAttrInit' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} // 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}} #ifdef GNU
int GlobalDeclAttrInit = 1; // expected-warning{{'GlobalDeclAttrInit' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} // 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 // Redeclarations
__declspec(dllimport) extern int GlobalRedecl1; __declspec(dllimport) extern int GlobalRedecl1;
@ -59,8 +91,7 @@ int *__attribute__((dllimport)) GlobalRedecl2b;
int GlobalRedecl2c __attribute__((dllimport)); int GlobalRedecl2c __attribute__((dllimport));
int GlobalRedecl2c __attribute__((dllimport)); int GlobalRedecl2c __attribute__((dllimport));
// NB: MSVC issues a warning and makes GlobalRedecl3 dllexport. We follow GCC // We follow GCC and drop the dllimport with a warning.
// and drop the dllimport with a warning.
__declspec(dllimport) extern int GlobalRedecl3; // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}} __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}} extern int GlobalRedecl3; // expected-warning{{'GlobalRedecl3' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
@ -133,13 +164,20 @@ inline void __attribute__((dllimport)) inlineFunc2() {}
__declspec(dllimport) void redecl1(); __declspec(dllimport) void redecl1();
__declspec(dllimport) void redecl1(); __declspec(dllimport) void redecl1();
// NB: MSVC issues a warning and makes redecl2/redecl3 dllexport. We follow GCC
// and drop the dllimport with a warning.
__declspec(dllimport) void redecl2(); // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}} __declspec(dllimport) void redecl2(); // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}}
void redecl2(); // expected-warning{{'redecl2' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} void redecl2(); // expected-warning{{'redecl2' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
__declspec(dllimport) void redecl3(); // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}} #ifdef GNU
void redecl3() {} // expected-warning{{'redecl3' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} // expected-note@+2{{previous attribute is here}}
#endif
__declspec(dllimport) void redecl3(); // expected-note{{previous declaration is here}}
// NB: Both MSVC and Clang issue a warning and make redecl3 dllexport.
#ifdef MS
// expected-warning@+4{{'redecl3' redeclared without 'dllimport' attribute: 'dllexport' attribute added}}
#else
// expected-warning@+2{{'redecl3' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
#endif
void redecl3() {}
void redecl4(); // expected-note{{previous declaration is here}} void redecl4(); // expected-note{{previous declaration is here}}
void useRedecl4() { redecl4(); } void useRedecl4() { redecl4(); }

View File

@ -44,17 +44,49 @@ __declspec(dllimport) int GlobalInit1 = 1; // expected-error{{definition of dlli
int __declspec(dllimport) GlobalInit2 = 1; // expected-error{{definition of dllimport data}} int __declspec(dllimport) GlobalInit2 = 1; // expected-error{{definition of dllimport data}}
// Declare, then reject definition. // Declare, then reject definition.
__declspec(dllimport) extern int ExternGlobalDeclInit; // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}} #ifdef GNU
int ExternGlobalDeclInit = 1; // expected-warning{{'ExternGlobalDeclInit' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} // 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}} #ifdef GNU
int GlobalDeclInit = 1; // expected-warning{{'GlobalDeclInit' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} // 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}} #ifdef GNU
int *GlobalDeclChunkAttrInit = 0; // expected-warning{{'GlobalDeclChunkAttrInit' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} // 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}} #ifdef GNU
int GlobalDeclAttrInit = 1; // expected-warning{{'GlobalDeclAttrInit' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} // 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 // Redeclarations
__declspec(dllimport) extern int GlobalRedecl1; __declspec(dllimport) extern int GlobalRedecl1;
@ -69,8 +101,6 @@ int *__attribute__((dllimport)) GlobalRedecl2b;
int GlobalRedecl2c __attribute__((dllimport)); int GlobalRedecl2c __attribute__((dllimport));
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}} __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}} extern int GlobalRedecl3; // expected-warning{{'GlobalRedecl3' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
@ -135,11 +165,31 @@ template<typename T> __declspec(dllimport) int VarTmplInit1 = 1; // expected-err
template<typename T> int __declspec(dllimport) VarTmplInit2 = 1; // expected-error{{definition of dllimport data}} template<typename T> int __declspec(dllimport) VarTmplInit2 = 1; // expected-error{{definition of dllimport data}}
// Declare, then reject definition. // Declare, then reject definition.
template<typename T> __declspec(dllimport) extern int ExternVarTmplDeclInit; // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}} #ifdef GNU
template<typename T> int ExternVarTmplDeclInit = 1; // expected-warning{{'ExternVarTmplDeclInit' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} // expected-note@+3{{previous attribute is here}}
#endif
template <typename T>
__declspec(dllimport) extern int ExternVarTmplDeclInit; // expected-note{{previous declaration is here}}
#ifdef MS
// expected-warning@+5{{'ExternVarTmplDeclInit' redeclared without 'dllimport' attribute: 'dllexport' attribute added}}
#else
// expected-warning@+3{{'ExternVarTmplDeclInit' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
#endif
template <typename T>
int ExternVarTmplDeclInit = 1;
template<typename T> __declspec(dllimport) int VarTmplDeclInit; // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}} #ifdef GNU
template<typename T> int VarTmplDeclInit = 1; // expected-warning{{'VarTmplDeclInit' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} // expected-note@+3{{previous attribute is here}}
#endif
template <typename T>
__declspec(dllimport) int VarTmplDeclInit; // expected-note{{previous declaration is here}}
#ifdef MS
// expected-warning@+5{{'VarTmplDeclInit' redeclared without 'dllimport' attribute: 'dllexport' attribute added}}
#else
// expected-warning@+3{{'VarTmplDeclInit' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
#endif
template <typename T>
int VarTmplDeclInit = 1;
// Redeclarations // Redeclarations
template<typename T> __declspec(dllimport) extern int VarTmplRedecl1; template<typename T> __declspec(dllimport) extern int VarTmplRedecl1;
@ -238,13 +288,20 @@ __declspec(dllimport) void inlineDef();
__declspec(dllimport) void redecl1(); __declspec(dllimport) void redecl1();
__declspec(dllimport) void redecl1(); __declspec(dllimport) void redecl1();
// NB: MSVC issues a warning and makes redecl2/redecl3 dllexport. We follow GCC
// and drop the dllimport with a warning.
__declspec(dllimport) void redecl2(); // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}} __declspec(dllimport) void redecl2(); // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}}
void redecl2(); // expected-warning{{'redecl2' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} void redecl2(); // expected-warning{{'redecl2' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
__declspec(dllimport) void redecl3(); // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}} #ifdef GNU
void redecl3() {} // expected-warning{{'redecl3' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} // expected-note@+2{{previous attribute is here}}
#endif
__declspec(dllimport) void redecl3(); // expected-note{{previous declaration is here}}
// NB: Both MSVC and Clang issue a warning and make redecl3 dllexport.
#ifdef MS
// expected-warning@+4{{'redecl3' redeclared without 'dllimport' attribute: 'dllexport' attribute added}}
#else
// expected-warning@+2{{'redecl3' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
#endif
void redecl3() {}
void redecl4(); // expected-note{{previous declaration is here}} void redecl4(); // expected-note{{previous declaration is here}}
__declspec(dllimport) void redecl4(); // expected-warning{{redeclaration of 'redecl4' should not add 'dllimport' attribute}} __declspec(dllimport) void redecl4(); // expected-warning{{redeclaration of 'redecl4' should not add 'dllimport' attribute}}
@ -266,7 +323,10 @@ __declspec(dllimport) inline void redecl6() {} // expected-warning{{'dllimport'
struct FuncFriend { struct FuncFriend {
friend __declspec(dllimport) void friend1(); friend __declspec(dllimport) void friend1();
friend __declspec(dllimport) void friend2(); // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}} friend __declspec(dllimport) void friend2(); // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}}
friend __declspec(dllimport) void friend3(); // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}} #ifdef GNU
// expected-note@+2{{previous attribute is here}}
#endif
friend __declspec(dllimport) void friend3(); // expected-note{{previous declaration is here}}
friend void friend4(); // expected-note{{previous declaration is here}} friend void friend4(); // expected-note{{previous declaration is here}}
#ifdef MS #ifdef MS
// expected-note@+2{{previous declaration is here}} // expected-note@+2{{previous declaration is here}}
@ -275,7 +335,12 @@ struct FuncFriend {
}; };
__declspec(dllimport) void friend1(); __declspec(dllimport) void friend1();
void friend2(); // expected-warning{{'friend2' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} void friend2(); // expected-warning{{'friend2' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
void friend3() {} // expected-warning{{'friend3' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} #ifdef MS
// expected-warning@+4{{'friend3' redeclared without 'dllimport' attribute: 'dllexport' attribute added}}
#else
// expected-warning@+2{{'friend3' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
#endif
void friend3() {}
__declspec(dllimport) void friend4(); // expected-warning{{redeclaration of 'friend4' should not add 'dllimport' attribute}} __declspec(dllimport) void friend4(); // expected-warning{{redeclaration of 'friend4' should not add 'dllimport' attribute}}
#ifdef MS #ifdef MS
__declspec(dllimport) inline void friend5() {} // expected-warning{{redeclaration of 'friend5' should not add 'dllimport' attribute}} __declspec(dllimport) inline void friend5() {} // expected-warning{{redeclaration of 'friend5' should not add 'dllimport' attribute}}
@ -447,33 +512,39 @@ template<> __declspec(dllimport) inline void funcTmpl<ExplicitSpec_InlineDef_Imp
struct ImportMembers { struct ImportMembers {
struct Nested { struct Nested {
__declspec(dllimport) void normalDecl(); __declspec(dllimport) void normalDecl();
__declspec(dllimport) void normalDef(); // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}} #ifdef GNU
// expected-note@+2{{previous attribute is here}}
#endif
__declspec(dllimport) void normalDef(); // expected-note{{previous declaration is here}}
}; };
#ifdef GNU #ifdef GNU
// expected-note@+5{{previous attribute is here}}
// expected-warning@+5{{'dllimport' attribute ignored on inline function}} // expected-warning@+5{{'dllimport' attribute ignored on inline function}}
// expected-warning@+6{{'dllimport' attribute ignored on inline function}} // expected-warning@+6{{'dllimport' attribute ignored on inline function}}
#endif #endif
__declspec(dllimport) void normalDecl(); __declspec(dllimport) void normalDecl();
__declspec(dllimport) void normalDef(); // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}} __declspec(dllimport) void normalDef(); // expected-note{{previous declaration is here}}
__declspec(dllimport) void normalInclass() {} __declspec(dllimport) void normalInclass() {}
__declspec(dllimport) void normalInlineDef(); __declspec(dllimport) void normalInlineDef();
__declspec(dllimport) inline void normalInlineDecl(); __declspec(dllimport) inline void normalInlineDecl();
#ifdef GNU #ifdef GNU
// expected-note@+5{{previous attribute is here}}
// expected-warning@+5{{'dllimport' attribute ignored on inline function}} // expected-warning@+5{{'dllimport' attribute ignored on inline function}}
// expected-warning@+6{{'dllimport' attribute ignored on inline function}} // expected-warning@+6{{'dllimport' attribute ignored on inline function}}
#endif #endif
__declspec(dllimport) virtual void virtualDecl(); __declspec(dllimport) virtual void virtualDecl();
__declspec(dllimport) virtual void virtualDef(); // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}} __declspec(dllimport) virtual void virtualDef(); // expected-note{{previous declaration is here}}
__declspec(dllimport) virtual void virtualInclass() {} __declspec(dllimport) virtual void virtualInclass() {}
__declspec(dllimport) virtual void virtualInlineDef(); __declspec(dllimport) virtual void virtualInlineDef();
__declspec(dllimport) virtual inline void virtualInlineDecl(); __declspec(dllimport) virtual inline void virtualInlineDecl();
#ifdef GNU #ifdef GNU
// expected-note@+5{{previous attribute is here}}
// expected-warning@+5{{'dllimport' attribute ignored on inline function}} // expected-warning@+5{{'dllimport' attribute ignored on inline function}}
// expected-warning@+6{{'dllimport' attribute ignored on inline function}} // expected-warning@+6{{'dllimport' attribute ignored on inline function}}
#endif #endif
__declspec(dllimport) static void staticDecl(); __declspec(dllimport) static void staticDecl();
__declspec(dllimport) static void staticDef(); // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}} __declspec(dllimport) static void staticDef(); // expected-note{{previous declaration is here}}
__declspec(dllimport) static void staticInclass() {} __declspec(dllimport) static void staticInclass() {}
__declspec(dllimport) static void staticInlineDef(); __declspec(dllimport) static void staticInlineDef();
__declspec(dllimport) static inline void staticInlineDecl(); __declspec(dllimport) static inline void staticInlineDecl();
@ -495,20 +566,40 @@ public:
__declspec(dllimport) constexpr static int ConstexprFieldDef = 1; // expected-note{{attribute is here}} __declspec(dllimport) constexpr static int ConstexprFieldDef = 1; // expected-note{{attribute is here}}
}; };
void ImportMembers::Nested::normalDef() {} // expected-warning{{'ImportMembers::Nested::normalDef' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} #ifdef MS
void ImportMembers::normalDef() {} // expected-warning{{'ImportMembers::normalDef' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} // expected-warning@+4{{'ImportMembers::Nested::normalDef' redeclared without 'dllimport' attribute: 'dllexport' attribute added}}
#else
// expected-warning@+2{{'ImportMembers::Nested::normalDef' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
#endif
void ImportMembers::Nested::normalDef() {}
#ifdef MS
// expected-warning@+4{{'ImportMembers::normalDef' redeclared without 'dllimport' attribute: 'dllexport' attribute added}}
#else
// expected-warning@+2{{'ImportMembers::normalDef' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
#endif
void ImportMembers::normalDef() {}
#ifdef GNU #ifdef GNU
// expected-warning@+2{{'ImportMembers::normalInlineDef' redeclared inline; 'dllimport' attribute ignored}} // expected-warning@+2{{'ImportMembers::normalInlineDef' redeclared inline; 'dllimport' attribute ignored}}
#endif #endif
inline void ImportMembers::normalInlineDef() {} inline void ImportMembers::normalInlineDef() {}
void ImportMembers::normalInlineDecl() {} void ImportMembers::normalInlineDecl() {}
void ImportMembers::virtualDef() {} // expected-warning{{'ImportMembers::virtualDef' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} #ifdef MS
// expected-warning@+4{{'ImportMembers::virtualDef' redeclared without 'dllimport' attribute: 'dllexport' attribute added}}
#else
// expected-warning@+2{{'ImportMembers::virtualDef' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
#endif
void ImportMembers::virtualDef() {}
#ifdef GNU #ifdef GNU
// expected-warning@+2{{'ImportMembers::virtualInlineDef' redeclared inline; 'dllimport' attribute ignored}} // expected-warning@+2{{'ImportMembers::virtualInlineDef' redeclared inline; 'dllimport' attribute ignored}}
#endif #endif
inline void ImportMembers::virtualInlineDef() {} inline void ImportMembers::virtualInlineDef() {}
void ImportMembers::virtualInlineDecl() {} void ImportMembers::virtualInlineDecl() {}
void ImportMembers::staticDef() {} // expected-warning{{'ImportMembers::staticDef' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} #ifdef MS
// expected-warning@+4{{'ImportMembers::staticDef' redeclared without 'dllimport' attribute: 'dllexport' attribute added}}
#else
// expected-warning@+2{{'ImportMembers::staticDef' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
#endif
void ImportMembers::staticDef() {}
#ifdef GNU #ifdef GNU
// expected-warning@+2{{'ImportMembers::staticInlineDef' redeclared inline; 'dllimport' attribute ignored}} // expected-warning@+2{{'ImportMembers::staticInlineDef' redeclared inline; 'dllimport' attribute ignored}}
#endif #endif
@ -620,7 +711,10 @@ struct ImportDefaulted {
// Import defaulted member function definitions. // Import defaulted member function definitions.
struct ImportDefaultedDefs { struct ImportDefaultedDefs {
__declspec(dllimport) ImportDefaultedDefs(); __declspec(dllimport) ImportDefaultedDefs();
__declspec(dllimport) ~ImportDefaultedDefs(); // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}} #ifdef GNU
// expected-note@+2{{previous attribute is here}}
#endif
__declspec(dllimport) ~ImportDefaultedDefs(); // expected-note{{previous declaration is here}}
#ifdef GNU #ifdef GNU
// expected-warning@+3{{'dllimport' attribute ignored on inline function}} // expected-warning@+3{{'dllimport' attribute ignored on inline function}}
@ -630,14 +724,22 @@ struct ImportDefaultedDefs {
__declspec(dllimport) ImportDefaultedDefs& operator=(const ImportDefaultedDefs&); __declspec(dllimport) ImportDefaultedDefs& operator=(const ImportDefaultedDefs&);
__declspec(dllimport) ImportDefaultedDefs(ImportDefaultedDefs&&); __declspec(dllimport) ImportDefaultedDefs(ImportDefaultedDefs&&);
__declspec(dllimport) ImportDefaultedDefs& operator=(ImportDefaultedDefs&&); // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}} #ifdef GNU
// expected-note@+2{{previous attribute is here}}
#endif
__declspec(dllimport) ImportDefaultedDefs &operator=(ImportDefaultedDefs &&); // expected-note{{previous declaration is here}}
}; };
// Not allowed on definitions. // Not allowed on definitions.
__declspec(dllimport) ImportDefaultedDefs::ImportDefaultedDefs() = default; // expected-error{{dllimport cannot be applied to non-inline function definition}} __declspec(dllimport) ImportDefaultedDefs::ImportDefaultedDefs() = default; // expected-error{{dllimport cannot be applied to non-inline function definition}}
#ifdef MS
// expected-warning@+5{{'ImportDefaultedDefs::~ImportDefaultedDefs' redeclared without 'dllimport' attribute: 'dllexport' attribute added}}
#else
// expected-warning@+3{{'ImportDefaultedDefs::~ImportDefaultedDefs' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
#endif
// dllimport cannot be dropped. // dllimport cannot be dropped.
ImportDefaultedDefs::~ImportDefaultedDefs() = default; // expected-warning{{'ImportDefaultedDefs::~ImportDefaultedDefs' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} ImportDefaultedDefs::~ImportDefaultedDefs() = default;
// Import inline declaration and definition. // Import inline declaration and definition.
#ifdef GNU #ifdef GNU
@ -648,8 +750,12 @@ __declspec(dllimport) ImportDefaultedDefs::ImportDefaultedDefs(const ImportDefau
inline ImportDefaultedDefs& ImportDefaultedDefs::operator=(const ImportDefaultedDefs&) = default; inline ImportDefaultedDefs& ImportDefaultedDefs::operator=(const ImportDefaultedDefs&) = default;
__declspec(dllimport) ImportDefaultedDefs::ImportDefaultedDefs(ImportDefaultedDefs&&) = default; // expected-error{{dllimport cannot be applied to non-inline function definition}} __declspec(dllimport) ImportDefaultedDefs::ImportDefaultedDefs(ImportDefaultedDefs&&) = default; // expected-error{{dllimport cannot be applied to non-inline function definition}}
ImportDefaultedDefs& ImportDefaultedDefs::operator=(ImportDefaultedDefs&&) = default; // expected-warning{{'ImportDefaultedDefs::operator=' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} #ifdef MS
// expected-warning@+4{{'ImportDefaultedDefs::operator=' redeclared without 'dllimport' attribute: 'dllexport' attribute added}}
#else
// expected-warning@+2{{'ImportDefaultedDefs::operator=' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
#endif
ImportDefaultedDefs &ImportDefaultedDefs::operator=(ImportDefaultedDefs &&) = default;
// Redeclarations cannot add dllimport. // Redeclarations cannot add dllimport.
struct MemberRedecl { struct MemberRedecl {
@ -970,13 +1076,22 @@ template<> __declspec(dllimport) const int MemVarTmpl::StaticVar<ExplicitSpec_De
template<typename T> template<typename T>
struct ImportClassTmplMembers { struct ImportClassTmplMembers {
__declspec(dllimport) void normalDecl(); __declspec(dllimport) void normalDecl();
__declspec(dllimport) void normalDef(); // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}} #ifdef GNU
// expected-note@+2{{previous attribute is here}}
#endif
__declspec(dllimport) void normalDef(); // expected-note{{previous declaration is here}}
__declspec(dllimport) void normalInlineDef(); __declspec(dllimport) void normalInlineDef();
__declspec(dllimport) virtual void virtualDecl(); __declspec(dllimport) virtual void virtualDecl();
__declspec(dllimport) virtual void virtualDef(); // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}} #ifdef GNU
// expected-note@+2{{previous attribute is here}}
#endif
__declspec(dllimport) virtual void virtualDef(); // expected-note{{previous declaration is here}}
__declspec(dllimport) virtual void virtualInlineDef(); __declspec(dllimport) virtual void virtualInlineDef();
__declspec(dllimport) static void staticDecl(); __declspec(dllimport) static void staticDecl();
__declspec(dllimport) static void staticDef(); // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}} #ifdef GNU
// expected-note@+2{{previous attribute is here}}
#endif
__declspec(dllimport) static void staticDef(); // expected-note{{previous declaration is here}}
__declspec(dllimport) static void staticInlineDef(); __declspec(dllimport) static void staticInlineDef();
#ifdef GNU #ifdef GNU
@ -1013,19 +1128,37 @@ public:
// NB: MSVC is inconsistent here and disallows *InlineDef on class templates, // NB: MSVC is inconsistent here and disallows *InlineDef on class templates,
// but allows it on classes. We allow both. // but allows it on classes. We allow both.
template<typename T> void ImportClassTmplMembers<T>::normalDef() {} // expected-warning{{'ImportClassTmplMembers::normalDef' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} #ifdef MS
// expected-warning@+5{{'ImportClassTmplMembers::normalDef' redeclared without 'dllimport' attribute: 'dllexport' attribute added}}
#else
// expected-warning@+3{{'ImportClassTmplMembers::normalDef' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
#endif
template <typename T>
void ImportClassTmplMembers<T>::normalDef() {}
#ifdef GNU #ifdef GNU
// expected-warning@+2{{'ImportClassTmplMembers::normalInlineDef' redeclared inline; 'dllimport' attribute ignored}} // expected-warning@+2{{'ImportClassTmplMembers::normalInlineDef' redeclared inline; 'dllimport' attribute ignored}}
#endif #endif
template<typename T> inline void ImportClassTmplMembers<T>::normalInlineDef() {} template<typename T> inline void ImportClassTmplMembers<T>::normalInlineDef() {}
template<typename T> void ImportClassTmplMembers<T>::normalInlineDecl() {} template<typename T> void ImportClassTmplMembers<T>::normalInlineDecl() {}
template<typename T> void ImportClassTmplMembers<T>::virtualDef() {} // expected-warning{{'ImportClassTmplMembers::virtualDef' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} #ifdef MS
// expected-warning@+5{{'ImportClassTmplMembers::virtualDef' redeclared without 'dllimport' attribute: 'dllexport' attribute added}}
#else
// expected-warning@+3{{'ImportClassTmplMembers::virtualDef' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
#endif
template <typename T>
void ImportClassTmplMembers<T>::virtualDef() {}
#ifdef GNU #ifdef GNU
// expected-warning@+2{{'ImportClassTmplMembers::virtualInlineDef' redeclared inline; 'dllimport' attribute ignored}} // expected-warning@+2{{'ImportClassTmplMembers::virtualInlineDef' redeclared inline; 'dllimport' attribute ignored}}
#endif #endif
template<typename T> inline void ImportClassTmplMembers<T>::virtualInlineDef() {} template<typename T> inline void ImportClassTmplMembers<T>::virtualInlineDef() {}
template<typename T> void ImportClassTmplMembers<T>::virtualInlineDecl() {} template<typename T> void ImportClassTmplMembers<T>::virtualInlineDecl() {}
template<typename T> void ImportClassTmplMembers<T>::staticDef() {} // expected-warning{{'ImportClassTmplMembers::staticDef' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} #ifdef MS
// expected-warning@+5{{'ImportClassTmplMembers::staticDef' redeclared without 'dllimport' attribute: 'dllexport' attribute added}}
#else
// expected-warning@+3{{'ImportClassTmplMembers::staticDef' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
#endif
template <typename T>
void ImportClassTmplMembers<T>::staticDef() {}
#ifdef GNU #ifdef GNU
// expected-warning@+2{{'ImportClassTmplMembers::staticInlineDef' redeclared inline; 'dllimport' attribute ignored}} // expected-warning@+2{{'ImportClassTmplMembers::staticInlineDef' redeclared inline; 'dllimport' attribute ignored}}
#endif #endif