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.

llvm-svn: 275610
This commit is contained in:
Saleem Abdulrasool 2016-07-15 20:41:10 +00:00
parent 4278047f64
commit 511f2e5a89
13 changed files with 222 additions and 30 deletions

View File

@ -2087,14 +2087,14 @@ def MSStruct : InheritableAttr {
def DLLExport : InheritableAttr, TargetSpecificAttr<TargetWindows> {
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<TargetWindows> {
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 {

View File

@ -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 = [{

View File

@ -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|"

View File

@ -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,

View File

@ -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}}

View File

@ -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}}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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";