From 9de0a57687b9dec5fd5b579175a526909a47afec Mon Sep 17 00:00:00 2001 From: Nico Rieck Date: Thu, 29 May 2014 16:51:19 +0000 Subject: [PATCH] Sema: Functions with dll attributes cannot be deleted llvm-svn: 209827 --- clang/include/clang/Basic/DiagnosticSemaKinds.td | 2 ++ clang/lib/Sema/SemaDeclCXX.cpp | 15 +++++++++++++++ clang/test/SemaCXX/dllexport.cpp | 16 ++++++++++++++++ clang/test/SemaCXX/dllimport.cpp | 19 +++++++++++++++++++ 4 files changed, 52 insertions(+) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index ac43a0c..d831008 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -2100,6 +2100,8 @@ def err_attribute_dll_redeclaration : Error< "redeclaration of %q0 cannot add %q1 attribute">; def err_attribute_dllimport_function_definition : Error< "dllimport cannot be applied to non-inline function definition">; +def err_attribute_dll_deleted : Error< + "attribute %q0 cannot be applied to a deleted function">; def err_attribute_dllimport_data_definition : Error< "definition of dllimport data">; def err_attribute_dllimport_static_field_definition : Error< diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 77d5a5b..da93b04 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -4348,6 +4348,15 @@ static void CheckAbstractClassUsage(AbstractUsageInfo &Info, } } +/// \brief Return a DLL attribute from the declaration. +static InheritableAttr *getDLLAttr(Decl *D) { + if (auto *Import = D->getAttr()) + return Import; + if (auto *Export = D->getAttr()) + return Export; + return nullptr; +} + /// \brief Perform semantic checks on a class definition that has been /// completing, introducing implicitly-declared members, checking for /// abstract types, etc. @@ -11971,6 +11980,12 @@ void Sema::SetDeclDeleted(Decl *Dcl, SourceLocation DelLoc) { Fn = Fn->getCanonicalDecl(); } + // dllimport/dllexport cannot be deleted. + if (const InheritableAttr *DLLAttr = getDLLAttr(Fn)) { + Diag(Fn->getLocation(), diag::err_attribute_dll_deleted) << DLLAttr; + Fn->setInvalidDecl(); + } + if (Fn->isDeleted()) return; diff --git a/clang/test/SemaCXX/dllexport.cpp b/clang/test/SemaCXX/dllexport.cpp index 510d34bb..c637e63 100644 --- a/clang/test/SemaCXX/dllexport.cpp +++ b/clang/test/SemaCXX/dllexport.cpp @@ -212,6 +212,10 @@ __declspec(dllexport) Internal internalRetFunc(); // expected-error{{'internalRe namespace { __declspec(dllexport) void internalFunc() {} } // expected-error{{'(anonymous namespace)::internalFunc' must have external linkage when declared 'dllexport'}} namespace ns { __declspec(dllexport) void externalFunc() {} } +// Export deleted function. +__declspec(dllexport) void deletedFunc() = delete; // expected-error{{attribute 'dllexport' cannot be applied to a deleted function}} +__declspec(dllexport) inline void deletedInlineFunc() = delete; // expected-error{{attribute 'dllexport' cannot be applied to a deleted function}} + //===----------------------------------------------------------------------===// @@ -474,6 +478,18 @@ void ExportAlloc::operator delete(void* p) { free(p); } void ExportAlloc::operator delete[](void* p) { free(p); } +// Export deleted member functions. +struct ExportDeleted { + __declspec(dllexport) ExportDeleted() = delete; // expected-error{{attribute 'dllexport' cannot be applied to a deleted function}} + __declspec(dllexport) ~ExportDeleted() = delete; // expected-error{{attribute 'dllexport' cannot be applied to a deleted function}} + __declspec(dllexport) ExportDeleted(const ExportDeleted&) = delete; // expected-error{{attribute 'dllexport' cannot be applied to a deleted function}} + __declspec(dllexport) ExportDeleted& operator=(const ExportDeleted&) = delete; // expected-error{{attribute 'dllexport' cannot be applied to a deleted function}} + __declspec(dllexport) ExportDeleted(ExportDeleted&&) = delete; // expected-error{{attribute 'dllexport' cannot be applied to a deleted function}} + __declspec(dllexport) ExportDeleted& operator=(ExportDeleted&&) = delete; // expected-error{{attribute 'dllexport' cannot be applied to a deleted function}} + __declspec(dllexport) void deleted() = delete; // expected-error{{attribute 'dllexport' cannot be applied to a deleted function}} +}; + + // Export defaulted member functions. struct ExportDefaulted { __declspec(dllexport) ExportDefaulted() = default; diff --git a/clang/test/SemaCXX/dllimport.cpp b/clang/test/SemaCXX/dllimport.cpp index dea8333..1f53f7a 100644 --- a/clang/test/SemaCXX/dllimport.cpp +++ b/clang/test/SemaCXX/dllimport.cpp @@ -252,6 +252,13 @@ __declspec(dllimport) Internal internalRetFunc(); // expected-error{{'internalRe namespace { __declspec(dllimport) void internalFunc(); } // expected-error{{'(anonymous namespace)::internalFunc' must have external linkage when declared 'dllimport'}} namespace ns { __declspec(dllimport) void externalFunc(); } +// Import deleted functions. +// FIXME: Deleted functions are definitions so a missing inline is diagnosed +// here which is irrelevant. But because the delete keyword is parsed later +// there is currently no straight-forward way to avoid this diagnostic. +__declspec(dllimport) void deletedFunc() = delete; // expected-error{{attribute 'dllimport' cannot be applied to a deleted function}} expected-error{{dllimport cannot be applied to non-inline function definition}} +__declspec(dllimport) inline void deletedInlineFunc() = delete; // expected-error{{attribute 'dllimport' cannot be applied to a deleted function}} + //===----------------------------------------------------------------------===// @@ -459,6 +466,18 @@ struct ImportSpecials { }; +// Import deleted member functions. +struct ImportDeleted { + __declspec(dllimport) ImportDeleted() = delete; // expected-error{{attribute 'dllimport' cannot be applied to a deleted function}} + __declspec(dllimport) ~ImportDeleted() = delete; // expected-error{{attribute 'dllimport' cannot be applied to a deleted function}} + __declspec(dllimport) ImportDeleted(const ImportDeleted&) = delete; // expected-error{{attribute 'dllimport' cannot be applied to a deleted function}} + __declspec(dllimport) ImportDeleted& operator=(const ImportDeleted&) = delete; // expected-error{{attribute 'dllimport' cannot be applied to a deleted function}} + __declspec(dllimport) ImportDeleted(ImportDeleted&&) = delete; // expected-error{{attribute 'dllimport' cannot be applied to a deleted function}} + __declspec(dllimport) ImportDeleted& operator=(ImportDeleted&&) = delete; // expected-error{{attribute 'dllimport' cannot be applied to a deleted function}} + __declspec(dllimport) void deleted() = delete; // expected-error{{attribute 'dllimport' cannot be applied to a deleted function}} +}; + + // Import allocation functions. struct ImportAlloc { __declspec(dllimport) void* operator new(__SIZE_TYPE__); -- 2.7.4