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
// Microsoft-related attributes
+def MsNoVTable : InheritableAttr {
+ let Spellings = [Declspec<"novtable">];
+ let Subjects = SubjectList<[CXXRecord]>;
+ let Documentation = [Undocumented];
+}
+
def MsProperty : IgnoredAttr {
let Spellings = [Declspec<"property">];
}
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 =
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);
}
}
else if (RD->hasAttr<DLLExportAttr>())
GV->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass);
+ if (!GV->hasExternalLinkage())
+ emitVBTableDefinition(VBT, RD, GV);
+
return GV;
}
break;
// Microsoft attributes:
+ case AttributeList::AT_MsNoVTable:
+ handleSimpleAttribute<MsNoVTableAttr>(S, D, Attr);
+ break;
case AttributeList::AT_MsStruct:
handleSimpleAttribute<MsStructAttr>(S, D, Attr);
break;
//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);