From: David Majnemer Date: Mon, 2 Feb 2015 10:22:20 +0000 (+0000) Subject: MS ABI: Implement support for 'novtable' X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=2ed5fe8195d2658ac4174c19fd0d06755dceef62;p=clang MS ABI: Implement support for 'novtable' It is common for COM interface classes to be marked as 'novtable' to tell the compiler that constructors and destructors should not reference virtual function tables. This commit implements this feature in clang. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@227796 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/Attr.td b/include/clang/Basic/Attr.td index 4087102140..00fc5be3cc 100644 --- a/include/clang/Basic/Attr.td +++ b/include/clang/Basic/Attr.td @@ -1761,6 +1761,12 @@ def TypeTagForDatatype : InheritableAttr { // Microsoft-related attributes +def MsNoVTable : InheritableAttr { + let Spellings = [Declspec<"novtable">]; + let Subjects = SubjectList<[CXXRecord]>; + let Documentation = [Undocumented]; +} + def MsProperty : IgnoredAttr { let Spellings = [Declspec<"property">]; } diff --git a/lib/CodeGen/CGClass.cpp b/lib/CodeGen/CGClass.cpp index d72eda95d7..459b7742a2 100644 --- a/lib/CodeGen/CGClass.cpp +++ b/lib/CodeGen/CGClass.cpp @@ -1949,6 +1949,14 @@ CodeGenFunction::InitializeVTablePointer(BaseSubobject Base, const CXXRecordDecl *NearestVBase, CharUnits OffsetFromNearestVBase, const CXXRecordDecl *VTableClass) { + const CXXRecordDecl *RD = Base.getBase(); + + // Don't initialize the vtable pointer if the class is marked with the + // 'novtable' attribute. + if ((RD == VTableClass || RD == NearestVBase) && + VTableClass->hasAttr()) + return; + // Compute the address point. bool NeedsVirtualOffset; llvm::Value *VTableAddressPoint = diff --git a/lib/CodeGen/MicrosoftCXXABI.cpp b/lib/CodeGen/MicrosoftCXXABI.cpp index 40f88f32a9..48adf3a23d 100644 --- a/lib/CodeGen/MicrosoftCXXABI.cpp +++ b/lib/CodeGen/MicrosoftCXXABI.cpp @@ -1582,7 +1582,8 @@ void MicrosoftCXXABI::emitVirtualInheritanceTables(const CXXRecordDecl *RD) { for (unsigned I = 0, E = VBGlobals.VBTables->size(); I != E; ++I) { const VPtrInfo *VBT = (*VBGlobals.VBTables)[I]; llvm::GlobalVariable *GV = VBGlobals.Globals[I]; - emitVBTableDefinition(*VBT, RD, GV); + if (GV->isDeclaration()) + emitVBTableDefinition(*VBT, RD, GV); } } @@ -1609,6 +1610,9 @@ MicrosoftCXXABI::getAddrOfVBTable(const VPtrInfo &VBT, const CXXRecordDecl *RD, else if (RD->hasAttr()) GV->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass); + if (!GV->hasExternalLinkage()) + emitVBTableDefinition(VBT, RD, GV); + return GV; } diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index 80f141ef8d..63695e8470 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -4689,6 +4689,9 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, break; // Microsoft attributes: + case AttributeList::AT_MsNoVTable: + handleSimpleAttribute(S, D, Attr); + break; case AttributeList::AT_MsStruct: handleSimpleAttribute(S, D, Attr); break; diff --git a/test/Parser/MicrosoftExtensions.cpp b/test/Parser/MicrosoftExtensions.cpp index 73a1bb57af..42689d141f 100644 --- a/test/Parser/MicrosoftExtensions.cpp +++ b/test/Parser/MicrosoftExtensions.cpp @@ -339,7 +339,7 @@ void TestProperty() { //expected-warning@+1 {{C++ operator 'and' (aka '&&') used as a macro name}} #define and foo -struct __declspec(uuid("00000000-0000-0000-C000-000000000046")) __declspec(novtable) IUnknown {}; // expected-warning{{__declspec attribute 'novtable' is not supported}} +struct __declspec(uuid("00000000-0000-0000-C000-000000000046")) __declspec(novtable) IUnknown {}; typedef bool (__stdcall __stdcall *blarg)(int);