diff options
| author | David Majnemer <david.majnemer@gmail.com> | 2015-02-02 10:22:20 +0000 |
|---|---|---|
| committer | David Majnemer <david.majnemer@gmail.com> | 2015-02-02 10:22:20 +0000 |
| commit | 129f417efdab746c92598fbf0b32f487db2d2f20 (patch) | |
| tree | 06da377b4b488a9884fc18eaa5929bc6827ec976 | |
| parent | 1f83bbb6feebb05f5ca7fb085d80eb5653476636 (diff) | |
| download | bcm5719-llvm-129f417efdab746c92598fbf0b32f487db2d2f20.tar.gz bcm5719-llvm-129f417efdab746c92598fbf0b32f487db2d2f20.zip | |
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.
llvm-svn: 227796
| -rw-r--r-- | clang/include/clang/Basic/Attr.td | 6 | ||||
| -rw-r--r-- | clang/lib/CodeGen/CGClass.cpp | 8 | ||||
| -rw-r--r-- | clang/lib/CodeGen/MicrosoftCXXABI.cpp | 6 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaDeclAttr.cpp | 3 | ||||
| -rw-r--r-- | clang/test/Parser/MicrosoftExtensions.cpp | 2 |
5 files changed, 23 insertions, 2 deletions
diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index 40871021405..00fc5be3cc0 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/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/clang/lib/CodeGen/CGClass.cpp b/clang/lib/CodeGen/CGClass.cpp index d72eda95d7c..459b7742a26 100644 --- a/clang/lib/CodeGen/CGClass.cpp +++ b/clang/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<MsNoVTableAttr>()) + return; + // Compute the address point. bool NeedsVirtualOffset; llvm::Value *VTableAddressPoint = diff --git a/clang/lib/CodeGen/MicrosoftCXXABI.cpp b/clang/lib/CodeGen/MicrosoftCXXABI.cpp index 40f88f32a99..48adf3a23d7 100644 --- a/clang/lib/CodeGen/MicrosoftCXXABI.cpp +++ b/clang/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<DLLExportAttr>()) GV->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass); + if (!GV->hasExternalLinkage()) + emitVBTableDefinition(VBT, RD, GV); + return GV; } diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 80f141ef8d0..63695e84703 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/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<MsNoVTableAttr>(S, D, Attr); + break; case AttributeList::AT_MsStruct: handleSimpleAttribute<MsStructAttr>(S, D, Attr); break; diff --git a/clang/test/Parser/MicrosoftExtensions.cpp b/clang/test/Parser/MicrosoftExtensions.cpp index 73a1bb57af3..42689d141f7 100644 --- a/clang/test/Parser/MicrosoftExtensions.cpp +++ b/clang/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); |

