From: Saleem Abdulrasool Date: Fri, 15 Jul 2016 20:41:10 +0000 (+0000) Subject: Sema: support __declspec(dll*) on ObjC interfaces X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=848b378c986629f3fce061cf71fec40fa112a086;p=clang Sema: support __declspec(dll*) on ObjC interfaces Extend the __declspec(dll*) attribute to cover ObjC interfaces. This was requested by Microsoft for their ObjC support. Cover both import and export. This only adds the semantic analysis portion of the support, code-generation still remains outstanding. Add some basic initial documentation on the attributes that were previously empty. Tweak the previous tests to use the relative expected-warnings to make the tests easier to read. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@275610 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/Attr.td b/include/clang/Basic/Attr.td index 7305c746ce..7da1efe5ff 100644 --- a/include/clang/Basic/Attr.td +++ b/include/clang/Basic/Attr.td @@ -2087,14 +2087,14 @@ def MSStruct : InheritableAttr { def DLLExport : InheritableAttr, TargetSpecificAttr { let Spellings = [Declspec<"dllexport">, GCC<"dllexport">]; - let Subjects = SubjectList<[Function, Var, CXXRecord]>; - let Documentation = [Undocumented]; + let Subjects = SubjectList<[Function, Var, CXXRecord, ObjCInterface]>; + let Documentation = [DLLExportDocs]; } def DLLImport : InheritableAttr, TargetSpecificAttr { let Spellings = [Declspec<"dllimport">, GCC<"dllimport">]; - let Subjects = SubjectList<[Function, Var, CXXRecord]>; - let Documentation = [Undocumented]; + let Subjects = SubjectList<[Function, Var, CXXRecord, ObjCInterface]>; + let Documentation = [DLLImportDocs]; } def SelectAny : InheritableAttr { diff --git a/include/clang/Basic/AttrDocs.td b/include/clang/Basic/AttrDocs.td index c7bddaacba..d0342bc603 100644 --- a/include/clang/Basic/AttrDocs.td +++ b/include/clang/Basic/AttrDocs.td @@ -67,6 +67,34 @@ TLS models are mutually exclusive. }]; } +def DLLExportDocs : Documentation { + let Category = DocCatVariable; + let Content = [{ +The ``__declspec(dllexport)`` attribute declares a variable, function, or +Objective-C interface to be exported from the module. It is available under the +``-fdeclspec`` flag for compatibility with various compilers. The primary use +is for COFF object files which explicitly specify what interfaces are available +for external use. See the dllexport_ documentation on MSDN for more +information. + +.. _dllexport: https://msdn.microsoft.com/en-us/library/3y1sfaz2.aspx + }]; +} + +def DLLImportDocs : Documentation { + let Category = DocCatVariable; + let Content = [{ +The ``__declspec(dllimport)`` attribute declares a variable, function, or +Objective-C interface to be imported from an external module. It is available +under the ``-fdeclspec`` flag for compatibility with various compilers. The +primary use is for COFF object files which explicitly specify what interfaces +are imported from external modules. See the dllimport_ documentation on MSDN +for more information. + +.. _dllimport: https://msdn.microsoft.com/en-us/library/3y1sfaz2.aspx + }]; +} + def ThreadDocs : Documentation { let Category = DocCatVariable; let Content = [{ diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 664853baeb..45e77d84d4 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -2503,7 +2503,9 @@ def err_ifunc_resolver_params : Error< "ifunc resolver function must have no parameters">; def warn_attribute_wrong_decl_type : Warning< "%0 attribute only applies to %select{functions|unions|" - "variables and functions|functions and methods|parameters|" + "variables and functions|" + "functions, variables, and Objective-C interfaces|" + "functions and methods|parameters|" "functions, methods and blocks|functions, methods, and classes|" "functions, methods, and parameters|classes|enums|variables|methods|" "fields and global variables|structs|parameters and typedefs|variables and typedefs|" @@ -2511,7 +2513,9 @@ def warn_attribute_wrong_decl_type : Warning< "types and namespaces|Objective-C interfaces|methods and properties|" "struct or union|struct, union or class|types|" "Objective-C instance methods|init methods of interface or class extension declarations|" - "variables, functions and classes|Objective-C protocols|" + "variables, functions and classes|" + "functions, variables, classes, and Objective-C interfaces|" + "Objective-C protocols|" "functions and global variables|structs, unions, and typedefs|structs and typedefs|" "interface or protocol declarations|kernel functions|non-K&R-style functions|" "variables, enums, fields and typedefs|functions, methods, enums, and classes|" diff --git a/include/clang/Sema/AttributeList.h b/include/clang/Sema/AttributeList.h index 5b838d3507..fcddbecc02 100644 --- a/include/clang/Sema/AttributeList.h +++ b/include/clang/Sema/AttributeList.h @@ -869,6 +869,7 @@ enum AttributeDeclKind { ExpectedFunction, ExpectedUnion, ExpectedVariableOrFunction, + ExpectedFunctionVariableOrObjCInterface, ExpectedFunctionOrMethod, ExpectedParameter, ExpectedFunctionMethodOrBlock, @@ -894,6 +895,7 @@ enum AttributeDeclKind { ExpectedObjCInstanceMethod, ExpectedObjCInterfaceDeclInitMethod, ExpectedFunctionVariableOrClass, + ExpectedFunctionVariableClassOrObjCInterface, ExpectedObjectiveCProtocol, ExpectedFunctionGlobalVarMethodOrProperty, ExpectedStructOrUnionOrTypedef, diff --git a/test/Sema/dllexport.c b/test/Sema/dllexport.c index 56c9e74225..7991a455b4 100644 --- a/test/Sema/dllexport.c +++ b/test/Sema/dllexport.c @@ -4,12 +4,18 @@ // RUN: %clang_cc1 -triple x86_64-mingw32 -fsyntax-only -fms-extensions -verify -std=c99 %s // Invalid usage. -__declspec(dllexport) typedef int typedef1; // expected-warning{{'dllexport' attribute only applies to variables and functions}} -typedef __declspec(dllexport) int typedef2; // expected-warning{{'dllexport' attribute only applies to variables and functions}} -typedef int __declspec(dllexport) typedef3; // expected-warning{{'dllexport' attribute only applies to variables and functions}} -typedef __declspec(dllexport) void (*FunTy)(); // expected-warning{{'dllexport' attribute only applies to variables and functions}} -enum __declspec(dllexport) Enum { EnumVal }; // expected-warning{{'dllexport' attribute only applies to variables and functions}} -struct __declspec(dllexport) Record {}; // expected-warning{{'dllexport' attribute only applies to variables and functions}} +__declspec(dllexport) typedef int typedef1; +// expected-warning@-1{{'dllexport' attribute only applies to variables and functions}} +typedef __declspec(dllexport) int typedef2; +// expected-warning@-1{{'dllexport' attribute only applies to variables and functions}} +typedef int __declspec(dllexport) typedef3; +// expected-warning@-1{{'dllexport' attribute only applies to variables and functions}} +typedef __declspec(dllexport) void (*FunTy)(); +// expected-warning@-1{{'dllexport' attribute only applies to variables and functions}} +enum __declspec(dllexport) Enum { EnumVal }; +// expected-warning@-1{{'dllexport' attribute only applies to variables and functions}} +struct __declspec(dllexport) Record {}; +// expected-warning@-1{{'dllexport' attribute only applies to variables and functions}} diff --git a/test/Sema/dllimport.c b/test/Sema/dllimport.c index 2da5dd8b40..0728cf14a8 100644 --- a/test/Sema/dllimport.c +++ b/test/Sema/dllimport.c @@ -4,12 +4,18 @@ // RUN: %clang_cc1 -triple x86_64-mingw32 -fsyntax-only -fms-extensions -verify -std=c99 -DGNU %s // Invalid usage. -__declspec(dllimport) typedef int typedef1; // expected-warning{{'dllimport' attribute only applies to variables and functions}} -typedef __declspec(dllimport) int typedef2; // expected-warning{{'dllimport' attribute only applies to variables and functions}} -typedef int __declspec(dllimport) typedef3; // expected-warning{{'dllimport' attribute only applies to variables and functions}} -typedef __declspec(dllimport) void (*FunTy)(); // expected-warning{{'dllimport' attribute only applies to variables and functions}} -enum __declspec(dllimport) Enum { EnumVal }; // expected-warning{{'dllimport' attribute only applies to variables and functions}} -struct __declspec(dllimport) Record {}; // expected-warning{{'dllimport' attribute only applies to variables and functions}} +__declspec(dllimport) typedef int typedef1; +// expected-warning@-1{{'dllimport' attribute only applies to variables and functions}} +typedef __declspec(dllimport) int typedef2; +// expected-warning@-1{{'dllimport' attribute only applies to variables and functions}} +typedef int __declspec(dllimport) typedef3; +// expected-warning@-1{{'dllimport' attribute only applies to variables and functions}} +typedef __declspec(dllimport) void (*FunTy)(); +// expected-warning@-1{{'dllimport' attribute only applies to variables and functions}} +enum __declspec(dllimport) Enum { EnumVal }; +// expected-warning@-1{{'dllimport' attribute only applies to variables and functions}} +struct __declspec(dllimport) Record {}; +// expected-warning@-1{{'dllimport' attribute only applies to variables and functions}} diff --git a/test/SemaCXX/dllexport.cpp b/test/SemaCXX/dllexport.cpp index 0bbf9b370b..b4850fc03d 100644 --- a/test/SemaCXX/dllexport.cpp +++ b/test/SemaCXX/dllexport.cpp @@ -16,13 +16,19 @@ struct External { int v; }; // Invalid usage. -__declspec(dllexport) typedef int typedef1; // expected-warning{{'dllexport' attribute only applies to variables, functions and classes}} -typedef __declspec(dllexport) int typedef2; // expected-warning{{'dllexport' attribute only applies to variables, functions and classes}} -typedef int __declspec(dllexport) typedef3; // expected-warning{{'dllexport' attribute only applies to variables, functions and classes}} -typedef __declspec(dllexport) void (*FunTy)(); // expected-warning{{'dllexport' attribute only applies to variables, functions and classes}} -enum __declspec(dllexport) Enum {}; // expected-warning{{'dllexport' attribute only applies to variables, functions and classes}} +__declspec(dllexport) typedef int typedef1; +// expected-warning@-1{{'dllexport' attribute only applies to variables, functions and classes}} +typedef __declspec(dllexport) int typedef2; +// expected-warning@-1{{'dllexport' attribute only applies to variables, functions and classes}} +typedef int __declspec(dllexport) typedef3; +// expected-warning@-1{{'dllexport' attribute only applies to variables, functions and classes}} +typedef __declspec(dllexport) void (*FunTy)(); +// expected-warning@-1{{'dllexport' attribute only applies to variables, functions and classes}} +enum __declspec(dllexport) Enum {}; +// expected-warning@-1{{'dllexport' attribute only applies to variables, functions and classes}} #if __has_feature(cxx_strong_enums) - enum class __declspec(dllexport) EnumClass {}; // expected-warning{{'dllexport' attribute only applies to variables, functions and classes}} +enum class __declspec(dllexport) EnumClass {}; +// expected-warning@-1{{'dllexport' attribute only applies to variables, functions and classes}} #endif diff --git a/test/SemaCXX/dllimport.cpp b/test/SemaCXX/dllimport.cpp index 3448e69bab..36a8ac625a 100644 --- a/test/SemaCXX/dllimport.cpp +++ b/test/SemaCXX/dllimport.cpp @@ -15,13 +15,19 @@ namespace { struct Internal {}; } // Invalid usage. -__declspec(dllimport) typedef int typedef1; // expected-warning{{'dllimport' attribute only applies to variables, functions and classes}} -typedef __declspec(dllimport) int typedef2; // expected-warning{{'dllimport' attribute only applies to variables, functions and classes}} -typedef int __declspec(dllimport) typedef3; // expected-warning{{'dllimport' attribute only applies to variables, functions and classes}} -typedef __declspec(dllimport) void (*FunTy)(); // expected-warning{{'dllimport' attribute only applies to variables, functions and classes}} -enum __declspec(dllimport) Enum {}; // expected-warning{{'dllimport' attribute only applies to variables, functions and classes}} +__declspec(dllimport) typedef int typedef1; +// expected-warning@-1{{'dllimport' attribute only applies to variables, functions and classes}} +typedef __declspec(dllimport) int typedef2; +// expected-warning@-1{{'dllimport' attribute only applies to variables, functions and classes}} +typedef int __declspec(dllimport) typedef3; +// expected-warning@-1{{'dllimport' attribute only applies to variables, functions and classes}} +typedef __declspec(dllimport) void (*FunTy)(); +// expected-warning@-1{{'dllimport' attribute only applies to variables, functions and classes}} +enum __declspec(dllimport) Enum {}; +// expected-warning@-1{{'dllimport' attribute only applies to variables, functions and classes}} #if __has_feature(cxx_strong_enums) - enum class __declspec(dllimport) EnumClass {}; // expected-warning{{'dllimport' attribute only applies to variables, functions and classes}} +enum class __declspec(dllimport) EnumClass {}; +// expected-warning@-1{{'dllimport' attribute only applies to variables, functions and classes}} #endif diff --git a/test/SemaObjC/dllexport.m b/test/SemaObjC/dllexport.m new file mode 100644 index 0000000000..e90b982c15 --- /dev/null +++ b/test/SemaObjC/dllexport.m @@ -0,0 +1,30 @@ +// RUN: %clang_cc1 -triple i686-windows -fdeclspec -fsyntax-only -verify %s + +__declspec(dllexport) typedef int typedef1; +// expected-warning@-1{{'dllexport' attribute only applies to functions, variables, and Objective-C interfaces}} +typedef __declspec(dllexport) int typedef2; +// expected-warning@-1{{'dllexport' attribute only applies to functions, variables, and Objective-C interfaces}} +typedef int __declspec(dllexport) typedef3; +// expected-warning@-1{{'dllexport' attribute only applies to functions, variables, and Objective-C interfaces}} +typedef __declspec(dllexport) void (*FunTy)(); +// expected-warning@-1{{'dllexport' attribute only applies to functions, variables, and Objective-C interfaces}} +enum __declspec(dllexport) E { Val }; +// expected-warning@-1{{'dllexport' attribute only applies to functions, variables, and Objective-C interfaces}} +struct __declspec(dllexport) Record {}; +// expected-warning@-1{{'dllexport' attribute only applies to functions, variables, and Objective-C interfaces}} + +__declspec(dllexport) +__attribute__((__objc_root_class__)) +@interface NSObject +@end + +__declspec(dllexport) +@interface I : NSObject +- (void)method; +@end + +@implementation I +- (void)method { +} +@end + diff --git a/test/SemaObjC/dllimport.m b/test/SemaObjC/dllimport.m new file mode 100644 index 0000000000..b8360773c6 --- /dev/null +++ b/test/SemaObjC/dllimport.m @@ -0,0 +1,30 @@ +// RUN: %clang_cc1 -triple i686-windows -fdeclspec -fsyntax-only -verify %s + +__declspec(dllimport) typedef int typedef1; +// expected-warning@-1{{'dllimport' attribute only applies to functions, variables, and Objective-C interfaces}} +typedef __declspec(dllimport) int typedef2; +// expected-warning@-1{{'dllimport' attribute only applies to functions, variables, and Objective-C interfaces}} +typedef int __declspec(dllimport) typedef3; +// expected-warning@-1{{'dllimport' attribute only applies to functions, variables, and Objective-C interfaces}} +typedef __declspec(dllimport) void (*FunTy)(); +// expected-warning@-1{{'dllimport' attribute only applies to functions, variables, and Objective-C interfaces}} +enum __declspec(dllimport) E { Val }; +// expected-warning@-1{{'dllimport' attribute only applies to functions, variables, and Objective-C interfaces}} +struct __declspec(dllimport) Record {}; +// expected-warning@-1{{'dllimport' attribute only applies to functions, variables, and Objective-C interfaces}} + +__declspec(dllimport) +__attribute__((__objc_root_class__)) +@interface NSObject +@end + +__declspec(dllimport) +@interface I : NSObject +- (void)method; +@end + +@implementation I +- (void)method { +} +@end + diff --git a/test/SemaObjCXX/dllexport.mm b/test/SemaObjCXX/dllexport.mm new file mode 100644 index 0000000000..739749f641 --- /dev/null +++ b/test/SemaObjCXX/dllexport.mm @@ -0,0 +1,33 @@ +// RUN: %clang_cc1 -triple i686-windows -fdeclspec -fsyntax-only -verify %s + +__declspec(dllexport) typedef int typedef1; +// expected-warning@-1{{'dllexport' attribute only applies to functions, variables, classes, and Objective-C interfaces}} +typedef __declspec(dllexport) int typedef2; +// expected-warning@-1{{'dllexport' attribute only applies to functions, variables, classes, and Objective-C interfaces}} +typedef int __declspec(dllexport) typedef3; +// expected-warning@-1{{'dllexport' attribute only applies to functions, variables, classes, and Objective-C interfaces}} +typedef __declspec(dllexport) void (*FunTy)(); +// expected-warning@-1{{'dllexport' attribute only applies to functions, variables, classes, and Objective-C interfaces}} +enum __declspec(dllexport) E { }; +// expected-warning@-1{{'dllexport' attribute only applies to functions, variables, classes, and Objective-C interfaces}} +#if __has_feature(cxx_strong_enums) +enum class __declspec(dllexport) F { }; +// expected-warning@-1{{'dllexport' attribute only applies to functions, variables, classes, and Objective-C interfaces}} +#endif + +__declspec(dllexport) +__attribute__((__objc_root_class__)) +@interface NSObject +@end + +__declspec(dllexport) +@interface I : NSObject +- (void)method; +@end + +@implementation I +- (void)method { +} +@end + + diff --git a/test/SemaObjCXX/dllimport.mm b/test/SemaObjCXX/dllimport.mm new file mode 100644 index 0000000000..4c348c4841 --- /dev/null +++ b/test/SemaObjCXX/dllimport.mm @@ -0,0 +1,32 @@ +// RUN: %clang_cc1 -triple i686-windows -fdeclspec -fsyntax-only -verify %s + +__declspec(dllimport) typedef int typedef1; +// expected-warning@-1{{'dllimport' attribute only applies to functions, variables, classes, and Objective-C interfaces}} +typedef __declspec(dllimport) int typedef2; +// expected-warning@-1{{'dllimport' attribute only applies to functions, variables, classes, and Objective-C interfaces}} +typedef int __declspec(dllimport) typedef3; +// expected-warning@-1{{'dllimport' attribute only applies to functions, variables, classes, and Objective-C interfaces}} +typedef __declspec(dllimport) void (*FunTy)(); +// expected-warning@-1{{'dllimport' attribute only applies to functions, variables, classes, and Objective-C interfaces}} +enum __declspec(dllimport) E { }; +// expected-warning@-1{{'dllimport' attribute only applies to functions, variables, classes, and Objective-C interfaces}} +#if __has_feature(cxx_strong_enums) +enum class __declspec(dllimport) F { }; +// expected-warning@-1{{'dllimport' attribute only applies to functions, variables, classes, and Objective-C interfaces}} +#endif + +__declspec(dllimport) +__attribute__((__objc_root_class__)) +@interface NSObject +@end + +__declspec(dllimport) +@interface I : NSObject +- (void)method; +@end + +@implementation I +- (void)method { +} +@end + diff --git a/utils/TableGen/ClangAttrEmitter.cpp b/utils/TableGen/ClangAttrEmitter.cpp index 1186d16ba2..50102af33a 100644 --- a/utils/TableGen/ClangAttrEmitter.cpp +++ b/utils/TableGen/ClangAttrEmitter.cpp @@ -2653,6 +2653,15 @@ static std::string CalculateDiagnostic(const Record &S) { return "(S.getLangOpts().CPlusPlus ? ExpectedFunctionVariableOrClass : " "ExpectedVariableOrFunction)"; + case Func | Var | Class | ObjCInterface: + return "(S.getLangOpts().CPlusPlus" + " ? ((S.getLangOpts().ObjC1 || S.getLangOpts().ObjC2)" + " ? ExpectedFunctionVariableClassOrObjCInterface" + " : ExpectedFunctionVariableOrClass)" + " : ((S.getLangOpts().ObjC1 || S.getLangOpts().ObjC2)" + " ? ExpectedFunctionVariableOrObjCInterface" + " : ExpectedVariableOrFunction))"; + case ObjCMethod | ObjCProp: return "ExpectedMethodOrProperty"; case ObjCProtocol | ObjCInterface: return "ExpectedObjectiveCInterfaceOrProtocol";