On Mon, Apr 4, 2016 at 3:34 PM, Wes Witt via cfe-commits <cfe-commits@lists.llvm.org> wrote: > Please accept this diff as a change to support dllimport of objective c > interfaces on windows. I’ve included a new test and changes to an existing > test as well. All clang tests pass on Linux & Windows. This change is > required for Microsoft’s use of the clang compiler in support of objective c > on windows.
Thank you for working on this! Some comments below: > diff --git a/include/clang/Basic/Attr.td b/include/clang/Basic/Attr.td > index c7a797c..dc22b27 100644 > --- a/include/clang/Basic/Attr.td > +++ b/include/clang/Basic/Attr.td > @@ -2023,7 +2023,8 @@ def DLLExport : InheritableAttr, > TargetSpecificAttr<TargetWindows> { > > def DLLImport : InheritableAttr, TargetSpecificAttr<TargetWindows> { > let Spellings = [Declspec<"dllimport">, GCC<"dllimport">]; > - let Subjects = SubjectList<[Function, Var, CXXRecord]>; > + let Subjects = SubjectList<[Function, Var, CXXRecord, ObjCInterface], > WarnDiag, > + "ExpectedFunctionVariableOrClass">; The diagnostic for this won't indicate that it's also okay to play on an Objective-C interface decl; is that intentional? > let Documentation = [Undocumented]; It would be nice to add some documentation to this, instead of leaving it totally undocumented. The docs can basically point to MSDN on __declspec(dllimport), but this would be a good place to let users know about the Objective-C behavior as well. > } > > diff --git a/lib/CodeGen/CGBlocks.cpp b/lib/CodeGen/CGBlocks.cpp > index ea164aa..9d2b2f9 100644 > --- a/lib/CodeGen/CGBlocks.cpp > +++ b/lib/CodeGen/CGBlocks.cpp > @@ -2334,5 +2334,9 @@ llvm::Constant > *CodeGenModule::getNSConcreteStackBlock() { > Int8PtrTy->getPointerTo(), > nullptr); > configureBlocksRuntimeObject(*this, NSConcreteStackBlock); > + if (getContext().getLangOpts().MSVCCompat) { > + auto *GV = > cast<llvm::GlobalValue>(NSConcreteStackBlock->stripPointerCasts()); > + GV->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass); > + } > return NSConcreteStackBlock; > } > diff --git a/lib/CodeGen/CGObjCGNU.cpp b/lib/CodeGen/CGObjCGNU.cpp > index bbe1b8b..dcb3a7d 100644 > --- a/lib/CodeGen/CGObjCGNU.cpp > +++ b/lib/CodeGen/CGObjCGNU.cpp > @@ -472,7 +472,7 @@ protected: > > /// Emits a pointer to the named class > virtual llvm::Value *GetClassNamed(CodeGenFunction &CGF, > - const std::string &Name, bool isWeak); > + StringRef Name, bool isWeak, bool > isDLLImport); > > /// Looks up the method for sending a message to the specified object. > This > /// mechanism differs between the GCC and GNU runtimes, so this method > must be > @@ -866,21 +866,24 @@ protected: > } > > llvm::Value *GetClassNamed(CodeGenFunction &CGF, > - const std::string &Name, bool isWeak) override { > + StringRef Name, bool isWeak, bool isDLLImport) > override { > if (isWeak) > - return CGObjCGNU::GetClassNamed(CGF, Name, isWeak); > + return CGObjCGNU::GetClassNamed(CGF, Name, isWeak, isDLLImport); > > EmitClassRef(Name); > > - std::string SymbolName = "_OBJC_CLASS_" + Name; > + std::string SymbolName = "_OBJC_CLASS_" + Name.str(); > > llvm::GlobalVariable *ClassSymbol = > TheModule.getGlobalVariable(SymbolName); > > - if (!ClassSymbol) > + if (!ClassSymbol) { > ClassSymbol = new llvm::GlobalVariable(TheModule, LongTy, false, > > llvm::GlobalValue::ExternalLinkage, > nullptr, SymbolName); > - > + if (isDLLImport) > + > ClassSymbol->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass); > + } > + > return ClassSymbol; > } > > @@ -1054,8 +1057,8 @@ CGObjCGNU::CGObjCGNU(CodeGenModule &cgm, unsigned > runtimeABIVersion, > } > > llvm::Value *CGObjCGNU::GetClassNamed(CodeGenFunction &CGF, > - const std::string &Name, > - bool isWeak) { > + StringRef Name, > + bool isWeak, bool isDLLImport) { > llvm::Constant *ClassName = MakeConstantString(Name); > // With the incompatible ABI, this will need to be replaced with a direct > // reference to the class symbol. For the compatible nonfragile ABI we are > @@ -1077,11 +1080,12 @@ llvm::Value *CGObjCGNU::GetClassNamed(CodeGenFunction > &CGF, > // techniques can modify the name -> class mapping. > llvm::Value *CGObjCGNU::GetClass(CodeGenFunction &CGF, > const ObjCInterfaceDecl *OID) { > - return GetClassNamed(CGF, OID->getNameAsString(), OID->isWeakImported()); > + return GetClassNamed(CGF, OID->getNameAsString(), OID->isWeakImported(), > + OID->hasAttr<DLLImportAttr>()); getNameAsString() returns a std::string, so the change to StringRef in GetClassNamed will add an extra conversion for no real purpose. Perhaps that should remain const std::string & instead? > } > > llvm::Value *CGObjCGNU::EmitNSAutoreleasePoolClassRef(CodeGenFunction &CGF) { > - return GetClassNamed(CGF, "NSAutoreleasePool", false); > + return GetClassNamed(CGF, "NSAutoreleasePool", false, > CGF.CGM.getTarget().getTriple().isKnownWindowsMSVCEnvironment()); > } > > llvm::Value *CGObjCGNU::GetSelector(CodeGenFunction &CGF, Selector Sel, > @@ -2878,7 +2882,10 @@ llvm::Value *CGObjCGNU::EmitIvarOffset(CodeGenFunction > &CGF, > const ObjCIvarDecl *Ivar) { > if (CGM.getLangOpts().ObjCRuntime.isNonFragile()) { > Interface = FindIvarInterface(CGM.getContext(), Interface, Ivar); > - if (RuntimeVersion < 10) > + // The MSVC linker cannot have a single global defined as > LinkOnceAnyLinkage and > + // ExternalLinkage, so create a reference to the ivar global and rely on > the > + // definition being created as part of GenerateClass. > + if (RuntimeVersion < 10 || > CGF.CGM.getTarget().getTriple().isKnownWindowsMSVCEnvironment()) > return CGF.Builder.CreateZExtOrBitCast( > CGF.Builder.CreateDefaultAlignedLoad(CGF.Builder.CreateAlignedLoad( > ObjCIvarOffsetVariable(Interface, Ivar), > diff --git a/test/Sema/dllimport.c b/test/Sema/dllimport.c > index f863499..b2e2d3c 100644 > --- a/test/Sema/dllimport.c > +++ b/test/Sema/dllimport.c > @@ -4,12 +4,12 @@ > // 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{{'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 { EnumVal }; // > expected-warning{{'dllimport' attribute only applies to variables, functions > and classes}} > +struct __declspec(dllimport) Record {}; // expected-warning{{'dllimport' > attribute only applies to variables, functions and classes}} > > > > diff --git a/test/SemaObjC/dllimport.m b/test/SemaObjC/dllimport.m > new file mode 100644 > index 0000000..b8fde7c > --- /dev/null > +++ b/test/SemaObjC/dllimport.m > @@ -0,0 +1,19 @@ > +// RUN: %clang -fsyntax-only -fms-extensions %s -Xclang -verify > +#if !__LP64__ > +// expected-no-diagnostics > +#endif > + > +@interface NSObject @end > + > +#if __LP64__ > +__declspec(dllimport) // expected-warning {{__declspec attribute 'dllimport' > is not supported}} > +#else > +__declspec(dllimport) > +#endif > +@interface testinterface : NSObject > +- (void)testmethod; > +@end > + > +@implementation testinterface > +- (void)testmethod { } > +@end > \ No newline at end of file Can you add a newline to the end of this file? ~Aaron _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits