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<TemplateDecl>(OldDecl)) + bool IsSpecialization, + bool IsDefinition = false) { + if (TemplateDecl *OldTD = dyn_cast<TemplateDecl>(OldDecl)) { OldDecl = OldTD->getTemplatedDecl(); + if (!IsSpecialization) + IsDefinition = false; + } if (TemplateDecl *NewTD = dyn_cast<TemplateDecl>(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<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 // separately. IsStaticDataMember = VD->isStaticDataMember(); + IsDefinition = + !VD->isThisDeclarationADefinition(S.Context) == VarDecl::DeclarationOnly; + } 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() && !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<DLLImportAttr>(); - NewDecl->dropAttr<DLLImportAttr>(); - } 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<DLLImportAttr>(); + NewDecl->dropAttr<DLLImportAttr>(); + 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<DLLImportAttr>(); + NewDecl->dropAttr<DLLImportAttr>(); + } + } else if (IsInline && OldImportAttr && !isMicrosoft) { // In MinGW, seeing a function declared inline drops the dllimport attribute. OldDecl->dropAttr<DLLImportAttr>(); NewDecl->dropAttr<DLLImportAttr>(); @@ -6369,7 +6393,8 @@ if (D.isRedeclaration() && !Previous.empty()) { checkDLLAttributeRedeclaration( *this, dyn_cast<NamedDecl>(Previous.getRepresentativeDecl()), NewVD, - IsExplicitSpecialization); + IsExplicitSpecialization, + D.isFunctionDefinition()); } if (NewTemplate) { @@ -8368,7 +8393,8 @@ if (D.isRedeclaration() && !Previous.empty()) { checkDLLAttributeRedeclaration( *this, dyn_cast<NamedDecl>(Previous.getRepresentativeDecl()), NewFD, - isExplicitSpecialization || isFunctionTemplateSpecialization); + isExplicitSpecialization || isFunctionTemplateSpecialization, + D.isFunctionDefinition()); } if (getLangOpts().CUDA) { Index: include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- include/clang/Basic/DiagnosticSemaKinds.td +++ include/clang/Basic/DiagnosticSemaKinds.td @@ -2351,6 +2351,9 @@ def warn_redeclaration_without_attribute_prev_attribute_ignored : Warning< "%q0 redeclared without %1 attribute: previous %1 ignored">, InGroup<DiagGroup<"inconsistent-dllimport">>; +def warn_redeclaration_without_import_attribute : Warning< + "%q0 redeclared without 'dllimport' attribute: 'dllexport' attribute added">, + InGroup<DiagGroup<"inconsistent-dllimport">>; def warn_dllimport_dropped_from_inline_function : Warning< "%q0 redeclared inline; %1 attribute ignored">, InGroup<IgnoredAttributes>; @@ -2884,6 +2887,7 @@ InGroup<DiagGroup<"unsupported-visibility">>; def err_mismatched_visibility: Error<"visibility does not match previous declaration">; def note_previous_attribute : Note<"previous attribute is here">; +def note_previous_attribute_replaced : Note<"previous attribute is here: replaced with 'dllexport'">; def note_conflicting_attribute : Note<"conflicting attribute is here">; def note_attribute : Note<"attribute is here">; def err_mismatched_ms_inheritance : Error< Index: test/SemaCXX/dllimport.cpp =================================================================== --- test/SemaCXX/dllimport.cpp +++ test/SemaCXX/dllimport.cpp @@ -45,16 +45,36 @@ // 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 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 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 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 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 +89,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}} @@ -136,10 +154,20 @@ // Declare, then reject definition. template<typename T> __declspec(dllimport) extern int ExternVarTmplDeclInit; // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}} -template<typename T> int ExternVarTmplDeclInit = 1; // expected-warning{{'ExternVarTmplDeclInit' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} +#ifdef MS +// expected-warning@+4{{'ExternVarTmplDeclInit' redeclared without 'dllimport' attribute: 'dllexport' attribute added}} +#else +// expected-warning@+2{{'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}} -template<typename T> int VarTmplDeclInit = 1; // expected-warning{{'VarTmplDeclInit' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} +#ifdef MS +// expected-warning@+4{{'VarTmplDeclInit' redeclared without 'dllimport' attribute: 'dllexport' attribute added}} +#else +// expected-warning@+2{{'VarTmplDeclInit' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} +#endif +template<typename T> int VarTmplDeclInit = 1; // Redeclarations template<typename T> __declspec(dllimport) extern int VarTmplRedecl1; @@ -238,13 +266,17 @@ __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}} 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}} - void redecl3() {} // expected-warning{{'redecl3' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} +// 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}} __declspec(dllimport) void redecl4(); // expected-warning{{redeclaration of 'redecl4' should not add 'dllimport' attribute}} @@ -275,7 +307,12 @@ }; __declspec(dllimport) void friend1(); 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}} #ifdef MS __declspec(dllimport) inline void friend5() {} // expected-warning{{redeclaration of 'friend5' should not add 'dllimport' attribute}} @@ -495,20 +532,40 @@ __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}} - void ImportMembers::normalDef() {} // expected-warning{{'ImportMembers::normalDef' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} +#ifdef MS +// 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 // expected-warning@+2{{'ImportMembers::normalInlineDef' redeclared inline; 'dllimport' attribute ignored}} #endif inline void ImportMembers::normalInlineDef() {} 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 // expected-warning@+2{{'ImportMembers::virtualInlineDef' redeclared inline; 'dllimport' attribute ignored}} #endif inline void ImportMembers::virtualInlineDef() {} 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 // expected-warning@+2{{'ImportMembers::staticInlineDef' redeclared inline; 'dllimport' attribute ignored}} #endif @@ -636,8 +693,13 @@ // Not allowed on definitions. __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. -ImportDefaultedDefs::~ImportDefaultedDefs() = default; // expected-warning{{'ImportDefaultedDefs::~ImportDefaultedDefs' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} +ImportDefaultedDefs::~ImportDefaultedDefs() = default; // Import inline declaration and definition. #ifdef GNU @@ -648,7 +710,12 @@ inline ImportDefaultedDefs& ImportDefaultedDefs::operator=(const ImportDefaultedDefs&) = default; __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. @@ -1013,19 +1080,34 @@ // NB: MSVC is inconsistent here and disallows *InlineDef on class templates, // 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@+4{{'ImportClassTmplMembers::normalDef' redeclared without 'dllimport' attribute: 'dllexport' attribute added}} +#else +// expected-warning@+2{{'ImportClassTmplMembers::normalDef' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} +#endif +template<typename T> void ImportClassTmplMembers<T>::normalDef() {} #ifdef GNU // expected-warning@+2{{'ImportClassTmplMembers::normalInlineDef' redeclared inline; 'dllimport' attribute ignored}} #endif template<typename T> inline void ImportClassTmplMembers<T>::normalInlineDef() {} 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@+4{{'ImportClassTmplMembers::virtualDef' redeclared without 'dllimport' attribute: 'dllexport' attribute added}} +#else +// expected-warning@+2{{'ImportClassTmplMembers::virtualDef' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} +#endif +template<typename T> void ImportClassTmplMembers<T>::virtualDef() {} #ifdef GNU // expected-warning@+2{{'ImportClassTmplMembers::virtualInlineDef' redeclared inline; 'dllimport' attribute ignored}} #endif template<typename T> inline void ImportClassTmplMembers<T>::virtualInlineDef() {} 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@+4{{'ImportClassTmplMembers::staticDef' redeclared without 'dllimport' attribute: 'dllexport' attribute added}} +#else +// expected-warning@+2{{'ImportClassTmplMembers::staticDef' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} +#endif +template<typename T> void ImportClassTmplMembers<T>::staticDef() {} #ifdef GNU // expected-warning@+2{{'ImportClassTmplMembers::staticInlineDef' redeclared inline; 'dllimport' attribute ignored}} #endif Index: test/CodeGen/dllimport.c =================================================================== --- test/CodeGen/dllimport.c +++ test/CodeGen/dllimport.c @@ -45,7 +45,8 @@ USEVAR(GlobalRedecl3) // 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; USEVAR(GlobalRedecl4) int GlobalRedecl4; // dllimport ignored @@ -111,13 +112,15 @@ void redecl2(void); USE(redecl2) -// CHECK-DAG: define void @redecl3() +// MS: define dllexport void @redecl3() +// GNU: define void @redecl3() __declspec(dllimport) void redecl3(void); void redecl3(void) {} // dllimport ignored USE(redecl3) // 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); USE(redecl4) void redecl4(void) {} // dllimport ignored Index: test/CodeGenCXX/dllimport-members.cpp =================================================================== --- test/CodeGenCXX/dllimport-members.cpp +++ test/CodeGenCXX/dllimport-members.cpp @@ -63,8 +63,8 @@ struct ImportMembers { struct Nested; - // M32-DAG: define x86_thiscallcc void @"\01?normalDef@ImportMembers@@QAEXXZ"(%struct.ImportMembers* %this) - // M64-DAG: define void @"\01?normalDef@ImportMembers@@QEAAXXZ"(%struct.ImportMembers* %this) + // M32-DAG: define dllexport x86_thiscallcc void @"\01?normalDef@ImportMembers@@QAEXXZ"(%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*) // M64-DAG: declare dllimport void @"\01?normalDecl@ImportMembers@@QEAAXXZ"(%struct.ImportMembers*) // M32-DAG: declare dllimport x86_thiscallcc void @"\01?normalInclass@ImportMembers@@QAEXXZ"(%struct.ImportMembers*) @@ -95,8 +95,8 @@ __declspec(dllimport) void normalInlineDef(); __declspec(dllimport) inline void normalInlineDecl(); - // M32-DAG: define x86_thiscallcc void @"\01?virtualDef@ImportMembers@@UAEXXZ"(%struct.ImportMembers* %this) - // M64-DAG: define void @"\01?virtualDef@ImportMembers@@UEAAXXZ"(%struct.ImportMembers* %this) + // M32-DAG: define dllexport x86_thiscallcc void @"\01?virtualDef@ImportMembers@@UAEXXZ"(%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*) // M64-DAG: declare dllimport void @"\01?virtualDecl@ImportMembers@@UEAAXXZ"(%struct.ImportMembers*) // M32-DAG: declare dllimport x86_thiscallcc void @"\01?virtualInclass@ImportMembers@@UAEXXZ"(%struct.ImportMembers*) @@ -127,7 +127,7 @@ __declspec(dllimport) virtual void virtualInlineDef(); __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?staticInclass@ImportMembers@@SAXXZ"() // MSC-DAG: declare dllimport void @"\01?staticInlineDef@ImportMembers@@SAXXZ"() @@ -235,8 +235,8 @@ // Import individual members of a nested class. struct ImportMembers::Nested { - // M32-DAG: define 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) + // M32-DAG: define dllexport x86_thiscallcc void @"\01?normalDef@Nested@ImportMembers@@QAEXXZ"(%"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"*) // 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"*) @@ -267,8 +267,8 @@ __declspec(dllimport) void normalInlineDef(); __declspec(dllimport) inline void normalInlineDecl(); - // M32-DAG: define 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) + // M32-DAG: define dllexport x86_thiscallcc void @"\01?virtualDef@Nested@ImportMembers@@UAEXXZ"(%"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"*) // 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"*) @@ -300,7 +300,7 @@ __declspec(dllimport) virtual void virtualInlineDef(); __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?staticInclass@Nested@ImportMembers@@SAXXZ"() // MSC-DAG: declare dllimport void @"\01?staticInlineDef@Nested@ImportMembers@@SAXXZ"() @@ -595,16 +595,16 @@ // 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; -// M32-DAG: define 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]+}})) +// 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 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]+}})) // 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]+}})) // G64-DAG: define void @_ZN19ImportDefaultedDefsC2EOS_(%struct.ImportDefaultedDefs* %this, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}})) 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]+}})) -// M64-DAG: define dereferenceable({{[0-9]+}}) %struct.ImportDefaultedDefs* @"\01??4ImportDefaultedDefs@@QEAAAEAU0@$$QEAU0@@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 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]+}})) // G64-DAG: define dereferenceable({{[0-9]+}}) %struct.ImportDefaultedDefs* @_ZN19ImportDefaultedDefsaSEOS_(%struct.ImportDefaultedDefs* %this, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}})) ImportDefaultedDefs& ImportDefaultedDefs::operator=(ImportDefaultedDefs&&) = default; // dllimport ignored Index: test/CodeGenCXX/dllimport.cpp =================================================================== --- test/CodeGenCXX/dllimport.cpp +++ test/CodeGenCXX/dllimport.cpp @@ -264,7 +264,7 @@ void redecl2(); USE(redecl2) -// MSC-DAG: define void @"\01?redecl3@@YAXXZ"() +// MSC-DAG: define dllexport void @"\01?redecl3@@YAXXZ"() // GNU-DAG: define void @_Z7redecl3v() __declspec(dllimport) void redecl3(); void redecl3() {} // dllimport ignored @@ -276,7 +276,7 @@ // GNU-DAG: declare dllimport void @_Z7friend1v() // MSC-DAG: declare void @"\01?friend2@@YAXXZ"() // 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() // MSC-DAG: declare void @"\01?friend4@@YAXXZ"() // GNU-DAG: declare void @_Z7friend4v() Index: test/Sema/dllimport.c =================================================================== --- test/Sema/dllimport.c +++ test/Sema/dllimport.c @@ -35,16 +35,36 @@ // 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 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 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 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 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; @@ -59,8 +79,7 @@ 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. +// 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}} @@ -133,13 +152,17 @@ __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}} 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}} - void redecl3() {} // expected-warning{{'redecl3' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} +// 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 useRedecl4() { redecl4(); }
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits