r245264 - Generating assumption loads of vptr after ctor call (fixed)
Piotr Padlewski via cfe-commits
cfe-commits at lists.llvm.org
Mon Aug 17 23:12:10 PDT 2015
Thanks. I have no idea what happen, but I will fix it tomorrow.
Piotr
On Mon, Aug 17, 2015 at 10:43 PM, Justin Bogner <mail at justinbogner.com>
wrote:
> Piotr Padlewski via cfe-commits <cfe-commits at lists.llvm.org> writes:
> > Author: prazek
> > Date: Mon Aug 17 22:52:00 2015
> > New Revision: 245264
> >
> > URL: http://llvm.org/viewvc/llvm-project?rev=245264&view=rev
> > Log:
> > Generating assumption loads of vptr after ctor call (fixed)
> >
> > Generating call assume(icmp %vtable, %global_vtable) after constructor
> > call for devirtualization purposes.
> >
> > For more info go to:
> > http://lists.llvm.org/pipermail/cfe-dev/2015-July/044227.html
> >
> > Edit:
> > Fixed version because of PR24479.
>
> (resending since I foolishly sent a very large text file and it got
> caught in moderation)
>
> This was hitting asserts on a couple of bootstrap bots, so I reverted
> it in r245267.
>
> Failing bots:
>
> http://lab.llvm.org:8080/green/job/clang-stage2-configure-Rlto_build/6382/
> http://bb.pgr.jp/builders/clang-3stage-i686-linux/builds/2969
>
> I also managed to grab the crash diagnostics from one of the bots, but
> the preprocessed source is too large for the list.
>
> > http://reviews.llvm.org/D11859
> >
> > Added:
> > cfe/trunk/test/CodeGenCXX/vtable-assume-load.cpp
> > Modified:
> > cfe/trunk/lib/CodeGen/CGCXXABI.h
> > cfe/trunk/lib/CodeGen/CGCall.cpp
> > cfe/trunk/lib/CodeGen/CGClass.cpp
> > cfe/trunk/lib/CodeGen/CodeGenFunction.h
> > cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp
> > cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp
> > cfe/trunk/test/CodeGen/available-externally-hidden.cpp
> > cfe/trunk/test/CodeGenCXX/ctor-globalopt.cpp
> > cfe/trunk/test/CodeGenCXX/template-instantiation.cpp
> > cfe/trunk/test/CodeGenCXX/thunks.cpp
> > cfe/trunk/test/CodeGenCXX/virtual-base-ctor.cpp
> > cfe/trunk/test/CodeGenCXX/vtable-available-externally.cpp
> >
> > Modified: cfe/trunk/lib/CodeGen/CGCXXABI.h
> > URL:
> >
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCXXABI.h?rev=245264&r1=245263&r2=245264&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/lib/CodeGen/CGCXXABI.h (original)
> > +++ cfe/trunk/lib/CodeGen/CGCXXABI.h Mon Aug 17 22:52:00 2015
> > @@ -346,13 +346,25 @@ public:
> > virtual void emitVTableDefinitions(CodeGenVTables &CGVT,
> > const CXXRecordDecl *RD) = 0;
> >
> > + /// Checks if ABI requires extra virtual offset for vtable field.
> > + virtual bool
> > + isVirtualOffsetNeededForVTableField(CodeGenFunction &CGF,
> > + CodeGenFunction::VPtr Vptr) = 0;
> > +
> > + /// Checks if ABI requires to initilize vptrs for given dynamic class.
> > + virtual bool doStructorsInitializeVPtrs(const CXXRecordDecl
> *VTableClass) = 0;
> > +
> > + /// Get the address point of the vtable for the given base subobject.
> > + virtual llvm::Constant *
> > + getVTableAddressPoint(BaseSubobject Base,
> > + const CXXRecordDecl *VTableClass) = 0;
> > +
> > /// Get the address point of the vtable for the given base subobject
> while
> > - /// building a constructor or a destructor. On return,
> NeedsVirtualOffset
> > - /// tells if a virtual base adjustment is needed in order to get the
> offset
> > - /// of the base subobject.
> > - virtual llvm::Value *getVTableAddressPointInStructor(
> > - CodeGenFunction &CGF, const CXXRecordDecl *RD, BaseSubobject Base,
> > - const CXXRecordDecl *NearestVBase, bool &NeedsVirtualOffset) = 0;
> > + /// building a constructor or a destructor.
> > + virtual llvm::Value *
> > + getVTableAddressPointInStructor(CodeGenFunction &CGF, const
> CXXRecordDecl *RD,
> > + BaseSubobject Base,
> > + const CXXRecordDecl *NearestVBase) =
> 0;
> >
> > /// Get the address point of the vtable for the given base subobject
> while
> > /// building a constexpr.
> >
> > Modified: cfe/trunk/lib/CodeGen/CGCall.cpp
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCall.cpp?rev=245264&r1=245263&r2=245264&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/lib/CodeGen/CGCall.cpp (original)
> > +++ cfe/trunk/lib/CodeGen/CGCall.cpp Mon Aug 17 22:52:00 2015
> > @@ -1412,7 +1412,8 @@ void CodeGenModule::ConstructAttributeLi
> >
> > if (const FunctionDecl *Fn = dyn_cast<FunctionDecl>(TargetDecl)) {
> > const FunctionProtoType *FPT =
> Fn->getType()->getAs<FunctionProtoType>();
> > - if (FPT && FPT->isNothrow(getContext()))
> > + if (FPT &&
> !isUnresolvedExceptionSpec(FPT->getExceptionSpecType()) &&
> > + FPT->isNothrow(getContext()))
> > FuncAttrs.addAttribute(llvm::Attribute::NoUnwind);
> > // Don't use [[noreturn]] or _Noreturn for a call to a virtual
> function.
> > // These attributes are not inherited by overloads.
> >
> > Modified: cfe/trunk/lib/CodeGen/CGClass.cpp
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGClass.cpp?rev=245264&r1=245263&r2=245264&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/lib/CodeGen/CGClass.cpp (original)
> > +++ cfe/trunk/lib/CodeGen/CGClass.cpp Mon Aug 17 22:52:00 2015
> > @@ -1806,12 +1806,14 @@ void CodeGenFunction::EmitCXXConstructor
> > bool ForVirtualBase,
> > bool Delegating,
> llvm::Value *This,
> > const CXXConstructExpr *E)
> {
> > + const CXXRecordDecl *ClassDecl = D->getParent();
> > +
> > // C++11 [class.mfct.non-static]p2:
> > // If a non-static member function of a class X is called for an
> object that
> > // is not of type X, or of a type derived from X, the behavior is
> undefined.
> > // FIXME: Provide a source location here.
> > EmitTypeCheck(CodeGenFunction::TCK_ConstructorCall, SourceLocation(),
> This,
> > - getContext().getRecordType(D->getParent()));
> > + getContext().getRecordType(ClassDecl));
> >
> > if (D->isTrivial() && D->isDefaultConstructor()) {
> > assert(E->getNumArgs() == 0 && "trivial default ctor with args");
> > @@ -1827,7 +1829,7 @@ void CodeGenFunction::EmitCXXConstructor
> > const Expr *Arg = E->getArg(0);
> > QualType SrcTy = Arg->getType();
> > llvm::Value *Src = EmitLValue(Arg).getAddress();
> > - QualType DestTy = getContext().getTypeDeclType(D->getParent());
> > + QualType DestTy = getContext().getTypeDeclType(ClassDecl);
> > EmitAggregateCopyCtor(This, Src, DestTy, SrcTy);
> > return;
> > }
> > @@ -1850,6 +1852,41 @@ void CodeGenFunction::EmitCXXConstructor
> > const CGFunctionInfo &Info =
> > CGM.getTypes().arrangeCXXConstructorCall(Args, D, Type,
> ExtraArgs);
> > EmitCall(Info, Callee, ReturnValueSlot(), Args, D);
> > +
> > + // Generate vtable assumptions if we're constructing a complete object
> > + // with a vtable. We don't do this for base subobjects for two
> reasons:
> > + // first, it's incorrect for classes with virtual bases, and second,
> we're
> > + // about to overwrite the vptrs anyway.
> > + if (CGM.getCodeGenOpts().OptimizationLevel > 0 &&
> > + ClassDecl->isDynamicClass() && Type != Ctor_Base)
> > + EmitVTableAssumptionLoads(ClassDecl, This);
> > +}
> > +
> > +void CodeGenFunction::EmitVTableAssumptionLoad(const VPtr &Vptr,
> > + llvm::Value *This) {
> > + llvm::Value *VTableGlobal =
> > + CGM.getCXXABI().getVTableAddressPoint(Vptr.Base,
> Vptr.VTableClass);
> > + if (!VTableGlobal)
> > + return;
> > +
> > + // We can just use the base offset in the complete class.
> > + CharUnits NonVirtualOffset = Vptr.Base.getBaseOffset();
> > +
> > + if (!NonVirtualOffset.isZero())
> > + This =
> > + ApplyNonVirtualAndVirtualOffset(*this, This, NonVirtualOffset,
> nullptr);
> > +
> > + llvm::Value *VPtrValue = GetVTablePtr(This, VTableGlobal->getType());
> > + llvm::Value *Cmp =
> > + Builder.CreateICmpEQ(VPtrValue, VTableGlobal, "cmp.vtables");
> > + Builder.CreateAssumption(Cmp);
> > +}
> > +
> > +void CodeGenFunction::EmitVTableAssumptionLoads(const CXXRecordDecl
> *ClassDecl,
> > + llvm::Value *This) {
> > + if (CGM.getCXXABI().doStructorsInitializeVPtrs(ClassDecl))
> > + for (const VPtr &Vptr : getVTablePointers(ClassDecl))
> > + EmitVTableAssumptionLoad(Vptr, This);
> > }
> >
> > void
> > @@ -2017,24 +2054,12 @@ void CodeGenFunction::PushDestructorClea
> > PushDestructorCleanup(D, Addr);
> > }
> >
> > -void
> > -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;
> > -
> > +void CodeGenFunction::InitializeVTablePointer(const VPtr &Vptr) {
> > // Compute the address point.
> > - bool NeedsVirtualOffset;
> > llvm::Value *VTableAddressPoint =
> > CGM.getCXXABI().getVTableAddressPointInStructor(
> > - *this, VTableClass, Base, NearestVBase, NeedsVirtualOffset);
> > + *this, Vptr.VTableClass, Vptr.Base, Vptr.NearestVBase);
> > +
> > if (!VTableAddressPoint)
> > return;
> >
> > @@ -2042,17 +2067,15 @@ CodeGenFunction::InitializeVTablePointer
> > llvm::Value *VirtualOffset = nullptr;
> > CharUnits NonVirtualOffset = CharUnits::Zero();
> >
> > - if (NeedsVirtualOffset) {
> > + if (CGM.getCXXABI().isVirtualOffsetNeededForVTableField(*this, Vptr))
> {
> > // We need to use the virtual base offset offset because the
> virtual base
> > // might have a different offset in the most derived class.
> > - VirtualOffset = CGM.getCXXABI().GetVirtualBaseClassOffset(*this,
> > -
> LoadCXXThis(),
> > -
> VTableClass,
> > -
> NearestVBase);
> > - NonVirtualOffset = OffsetFromNearestVBase;
> > + VirtualOffset = CGM.getCXXABI().GetVirtualBaseClassOffset(
> > + *this, LoadCXXThis(), Vptr.VTableClass, Vptr.NearestVBase);
> > + NonVirtualOffset = Vptr.OffsetFromNearestVBase;
> > } else {
> > // We can just use the base offset in the complete class.
> > - NonVirtualOffset = Base.getBaseOffset();
> > + NonVirtualOffset = Vptr.Base.getBaseOffset();
> > }
> >
> > // Apply the offsets.
> > @@ -2071,23 +2094,36 @@ CodeGenFunction::InitializeVTablePointer
> > ->getPointerTo();
> > VTableField = Builder.CreateBitCast(VTableField,
> VTablePtrTy->getPointerTo());
> > VTableAddressPoint = Builder.CreateBitCast(VTableAddressPoint,
> VTablePtrTy);
> > +
> > llvm::StoreInst *Store = Builder.CreateStore(VTableAddressPoint,
> VTableField);
> > CGM.DecorateInstruction(Store, CGM.getTBAAInfoForVTablePtr());
> > }
> >
> > -void
> > -CodeGenFunction::InitializeVTablePointers(BaseSubobject Base,
> > - const CXXRecordDecl
> *NearestVBase,
> > - CharUnits
> OffsetFromNearestVBase,
> > - bool
> BaseIsNonVirtualPrimaryBase,
> > - const CXXRecordDecl
> *VTableClass,
> > - VisitedVirtualBasesSetTy&
> VBases) {
> > +CodeGenFunction::VPtrsVector
> > +CodeGenFunction::getVTablePointers(const CXXRecordDecl *VTableClass) {
> > + CodeGenFunction::VPtrsVector VPtrsResult;
> > + VisitedVirtualBasesSetTy VBases;
> > + getVTablePointers(BaseSubobject(VTableClass, CharUnits::Zero()),
> > + /*NearestVBase=*/nullptr,
> > + /*OffsetFromNearestVBase=*/CharUnits::Zero(),
> > + /*BaseIsNonVirtualPrimaryBase=*/false, VTableClass,
> VBases,
> > + VPtrsResult);
> > + return VPtrsResult;
> > +}
> > +
> > +void CodeGenFunction::getVTablePointers(BaseSubobject Base,
> > + const CXXRecordDecl
> *NearestVBase,
> > + CharUnits
> OffsetFromNearestVBase,
> > + bool
> BaseIsNonVirtualPrimaryBase,
> > + const CXXRecordDecl
> *VTableClass,
> > + VisitedVirtualBasesSetTy
> &VBases,
> > + VPtrsVector &Vptrs) {
> > // If this base is a non-virtual primary base the address point has
> already
> > // been set.
> > if (!BaseIsNonVirtualPrimaryBase) {
> > // Initialize the vtable pointer for this base.
> > - InitializeVTablePointer(Base, NearestVBase, OffsetFromNearestVBase,
> > - VTableClass);
> > + VPtr Vptr = {Base, NearestVBase, OffsetFromNearestVBase,
> VTableClass};
> > + Vptrs.push_back(Vptr);
> > }
> >
> > const CXXRecordDecl *RD = Base.getBase();
> > @@ -2125,11 +2161,10 @@ CodeGenFunction::InitializeVTablePointer
> > BaseDeclIsNonVirtualPrimaryBase = Layout.getPrimaryBase() ==
> BaseDecl;
> > }
> >
> > - InitializeVTablePointers(BaseSubobject(BaseDecl, BaseOffset),
> > - I.isVirtual() ? BaseDecl : NearestVBase,
> > - BaseOffsetFromNearestVBase,
> > - BaseDeclIsNonVirtualPrimaryBase,
> > - VTableClass, VBases);
> > + getVTablePointers(
> > + BaseSubobject(BaseDecl, BaseOffset),
> > + I.isVirtual() ? BaseDecl : NearestVBase,
> BaseOffsetFromNearestVBase,
> > + BaseDeclIsNonVirtualPrimaryBase, VTableClass, VBases, Vptrs);
> > }
> > }
> >
> > @@ -2139,11 +2174,9 @@ void CodeGenFunction::InitializeVTablePo
> > return;
> >
> > // Initialize the vtable pointers for this class and all of its bases.
> > - VisitedVirtualBasesSetTy VBases;
> > - InitializeVTablePointers(BaseSubobject(RD, CharUnits::Zero()),
> > - /*NearestVBase=*/nullptr,
> > - /*OffsetFromNearestVBase=*/CharUnits::Zero(),
> > - /*BaseIsNonVirtualPrimaryBase=*/false, RD,
> VBases);
> > + if (CGM.getCXXABI().doStructorsInitializeVPtrs(RD))
> > + for (const VPtr &Vptr : getVTablePointers(RD))
> > + InitializeVTablePointer(Vptr);
> >
> > if (RD->getNumVBases())
> > CGM.getCXXABI().initializeHiddenVirtualInheritanceMembers(*this,
> RD);
> >
> > Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.h
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.h?rev=245264&r1=245263&r2=245264&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/lib/CodeGen/CodeGenFunction.h (original)
> > +++ cfe/trunk/lib/CodeGen/CodeGenFunction.h Mon Aug 17 22:52:00 2015
> > @@ -1309,21 +1309,27 @@ public:
> > void EmitInitializerForField(FieldDecl *Field, LValue LHS, Expr *Init,
> > ArrayRef<VarDecl *> ArrayIndexes);
> >
> > - /// InitializeVTablePointer - Initialize the vtable pointer of the
> given
> > - /// subobject.
> > - ///
> > - void InitializeVTablePointer(BaseSubobject Base,
> > - const CXXRecordDecl *NearestVBase,
> > - CharUnits OffsetFromNearestVBase,
> > - const CXXRecordDecl *VTableClass);
> > + /// Struct with all informations about dynamic [sub]class needed to
> set vptr.
> > + struct VPtr {
> > + BaseSubobject Base;
> > + const CXXRecordDecl *NearestVBase;
> > + CharUnits OffsetFromNearestVBase;
> > + const CXXRecordDecl *VTableClass;
> > + };
> > +
> > + /// Initialize the vtable pointer of the given subobject.
> > + void InitializeVTablePointer(const VPtr &vptr);
> > +
> > + typedef llvm::SmallVector<VPtr, 4> VPtrsVector;
> >
> > typedef llvm::SmallPtrSet<const CXXRecordDecl *, 4>
> VisitedVirtualBasesSetTy;
> > - void InitializeVTablePointers(BaseSubobject Base,
> > - const CXXRecordDecl *NearestVBase,
> > - CharUnits OffsetFromNearestVBase,
> > - bool BaseIsNonVirtualPrimaryBase,
> > - const CXXRecordDecl *VTableClass,
> > - VisitedVirtualBasesSetTy& VBases);
> > + VPtrsVector getVTablePointers(const CXXRecordDecl *VTableClass);
> > +
> > + void getVTablePointers(BaseSubobject Base, const CXXRecordDecl
> *NearestVBase,
> > + CharUnits OffsetFromNearestVBase,
> > + bool BaseIsNonVirtualPrimaryBase,
> > + const CXXRecordDecl *VTableClass,
> > + VisitedVirtualBasesSetTy &VBases, VPtrsVector
> &vptrs);
> >
> > void InitializeVTablePointers(const CXXRecordDecl *ClassDecl);
> >
> > @@ -1752,10 +1758,19 @@ public:
> > // they are substantially the same.
> > void EmitDelegatingCXXConstructorCall(const CXXConstructorDecl *Ctor,
> > const FunctionArgList &Args);
> > +
> > void EmitCXXConstructorCall(const CXXConstructorDecl *D, CXXCtorType
> Type,
> > bool ForVirtualBase, bool Delegating,
> > llvm::Value *This, const CXXConstructExpr
> *E);
> >
> > + /// Emit assumption load for all bases. Requires to be be called only
> on
> > + /// most-derived class and not under construction of the object.
> > + void EmitVTableAssumptionLoads(const CXXRecordDecl *ClassDecl,
> > + llvm::Value *This);
> > +
> > + /// Emit assumption that vptr load == global vtable.
> > + void EmitVTableAssumptionLoad(const VPtr &vptr, llvm::Value *This);
> > +
> > void EmitSynthesizedCXXCopyCtorCall(const CXXConstructorDecl *D,
> > llvm::Value *This, llvm::Value *Src,
> > const CXXConstructExpr *E);
> >
> > Modified: cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp?rev=245264&r1=245263&r2=245264&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp (original)
> > +++ cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp Mon Aug 17 22:52:00 2015
> > @@ -190,10 +190,24 @@ public:
> > void emitVTableDefinitions(CodeGenVTables &CGVT,
> > const CXXRecordDecl *RD) override;
> >
> > + bool isVirtualOffsetNeededForVTableField(CodeGenFunction &CGF,
> > + CodeGenFunction::VPtr Vptr)
> override;
> > +
> > + bool doStructorsInitializeVPtrs(const CXXRecordDecl *VTableClass)
> override {
> > + return true;
> > + }
> > +
> > + llvm::Constant *
> > + getVTableAddressPoint(BaseSubobject Base,
> > + const CXXRecordDecl *VTableClass) override;
> > +
> > llvm::Value *getVTableAddressPointInStructor(
> > CodeGenFunction &CGF, const CXXRecordDecl *VTableClass,
> > - BaseSubobject Base, const CXXRecordDecl *NearestVBase,
> > - bool &NeedsVirtualOffset) override;
> > + BaseSubobject Base, const CXXRecordDecl *NearestVBase) override;
> > +
> > + llvm::Value *getVTableAddressPointInStructorWithVTT(
> > + CodeGenFunction &CGF, const CXXRecordDecl *VTableClass,
> > + BaseSubobject Base, const CXXRecordDecl *NearestVBase);
> >
> > llvm::Constant *
> > getVTableAddressPointForConstExpr(BaseSubobject Base,
> > @@ -1376,41 +1390,29 @@ void ItaniumCXXABI::emitVTableDefinition
> > CGM.EmitVTableBitSetEntries(VTable, VTLayout);
> > }
> >
> > +bool ItaniumCXXABI::isVirtualOffsetNeededForVTableField(
> > + CodeGenFunction &CGF, CodeGenFunction::VPtr Vptr) {
> > + if (Vptr.NearestVBase == nullptr)
> > + return false;
> > + return NeedsVTTParameter(CGF.CurGD);
> > +}
> > +
> > llvm::Value *ItaniumCXXABI::getVTableAddressPointInStructor(
> > CodeGenFunction &CGF, const CXXRecordDecl *VTableClass,
> BaseSubobject Base,
> > - const CXXRecordDecl *NearestVBase, bool &NeedsVirtualOffset) {
> > - bool NeedsVTTParam = CGM.getCXXABI().NeedsVTTParameter(CGF.CurGD);
> > - NeedsVirtualOffset = (NeedsVTTParam && NearestVBase);
> > -
> > - llvm::Value *VTableAddressPoint;
> > - if (NeedsVTTParam && (Base.getBase()->getNumVBases() ||
> NearestVBase)) {
> > - // Get the secondary vpointer index.
> > - uint64_t VirtualPointerIndex =
> > - CGM.getVTables().getSecondaryVirtualPointerIndex(VTableClass,
> Base);
> > -
> > - /// Load the VTT.
> > - llvm::Value *VTT = CGF.LoadCXXVTT();
> > - if (VirtualPointerIndex)
> > - VTT = CGF.Builder.CreateConstInBoundsGEP1_64(VTT,
> VirtualPointerIndex);
> > + const CXXRecordDecl *NearestVBase) {
> >
> > - // And load the address point from the VTT.
> > - VTableAddressPoint = CGF.Builder.CreateLoad(VTT);
> > - } else {
> > - llvm::Constant *VTable =
> > - CGM.getCXXABI().getAddrOfVTable(VTableClass, CharUnits());
> > - uint64_t AddressPoint = CGM.getItaniumVTableContext()
> > - .getVTableLayout(VTableClass)
> > - .getAddressPoint(Base);
> > - VTableAddressPoint =
> > - CGF.Builder.CreateConstInBoundsGEP2_64(VTable, 0, AddressPoint);
> > + if ((Base.getBase()->getNumVBases() || NearestVBase != nullptr) &&
> > + NeedsVTTParameter(CGF.CurGD)) {
> > + return getVTableAddressPointInStructorWithVTT(CGF, VTableClass,
> Base,
> > + NearestVBase);
> > }
> > -
> > - return VTableAddressPoint;
> > + return getVTableAddressPoint(Base, VTableClass);
> > }
> >
> > -llvm::Constant *ItaniumCXXABI::getVTableAddressPointForConstExpr(
> > - BaseSubobject Base, const CXXRecordDecl *VTableClass) {
> > - auto *VTable = getAddrOfVTable(VTableClass, CharUnits());
> > +llvm::Constant *
> > +ItaniumCXXABI::getVTableAddressPoint(BaseSubobject Base,
> > + const CXXRecordDecl *VTableClass) {
> > + llvm::GlobalValue *VTable = getAddrOfVTable(VTableClass, CharUnits());
> >
> > // Find the appropriate vtable within the vtable group.
> > uint64_t AddressPoint = CGM.getItaniumVTableContext()
> > @@ -1425,6 +1427,30 @@ llvm::Constant *ItaniumCXXABI::getVTable
> > VTable, Indices);
> > }
> >
> > +llvm::Value *ItaniumCXXABI::getVTableAddressPointInStructorWithVTT(
> > + CodeGenFunction &CGF, const CXXRecordDecl *VTableClass,
> BaseSubobject Base,
> > + const CXXRecordDecl *NearestVBase) {
> > + assert((Base.getBase()->getNumVBases() || NearestVBase != nullptr) &&
> > + NeedsVTTParameter(CGF.CurGD) && "This class doesn't have VTT");
> > +
> > + // Get the secondary vpointer index.
> > + uint64_t VirtualPointerIndex =
> > + CGM.getVTables().getSecondaryVirtualPointerIndex(VTableClass,
> Base);
> > +
> > + /// Load the VTT.
> > + llvm::Value *VTT = CGF.LoadCXXVTT();
> > + if (VirtualPointerIndex)
> > + VTT = CGF.Builder.CreateConstInBoundsGEP1_64(VTT,
> VirtualPointerIndex);
> > +
> > + // And load the address point from the VTT.
> > + return CGF.Builder.CreateLoad(VTT);
> > +}
> > +
> > +llvm::Constant *ItaniumCXXABI::getVTableAddressPointForConstExpr(
> > + BaseSubobject Base, const CXXRecordDecl *VTableClass) {
> > + return getVTableAddressPoint(Base, VTableClass);
> > +}
> > +
> > llvm::GlobalVariable *ItaniumCXXABI::getAddrOfVTable(const
> CXXRecordDecl *RD,
> > CharUnits
> VPtrOffset) {
> > assert(VPtrOffset.isZero() && "Itanium ABI only supports zero vptr
> offsets");
> >
> > Modified: cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp?rev=245264&r1=245263&r2=245264&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp (original)
> > +++ cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp Mon Aug 17 22:52:00 2015
> > @@ -215,10 +215,22 @@ public:
> > void emitVTableDefinitions(CodeGenVTables &CGVT,
> > const CXXRecordDecl *RD) override;
> >
> > + bool isVirtualOffsetNeededForVTableField(CodeGenFunction &CGF,
> > + CodeGenFunction::VPtr Vptr)
> override;
> > +
> > + /// Don't initialize vptrs if dynamic class
> > + /// is marked with with the 'novtable' attribute.
> > + bool doStructorsInitializeVPtrs(const CXXRecordDecl *VTableClass)
> override {
> > + return !VTableClass->hasAttr<MSNoVTableAttr>();
> > + }
> > +
> > + llvm::Constant *
> > + getVTableAddressPoint(BaseSubobject Base,
> > + const CXXRecordDecl *VTableClass) override;
> > +
> > llvm::Value *getVTableAddressPointInStructor(
> > CodeGenFunction &CGF, const CXXRecordDecl *VTableClass,
> > - BaseSubobject Base, const CXXRecordDecl *NearestVBase,
> > - bool &NeedsVirtualOffset) override;
> > + BaseSubobject Base, const CXXRecordDecl *NearestVBase) override;
> >
> > llvm::Constant *
> > getVTableAddressPointForConstExpr(BaseSubobject Base,
> > @@ -1568,14 +1580,15 @@ void MicrosoftCXXABI::emitVTableDefiniti
> > }
> > }
> >
> > +bool MicrosoftCXXABI::isVirtualOffsetNeededForVTableField(
> > + CodeGenFunction &CGF, CodeGenFunction::VPtr Vptr) {
> > + return Vptr.NearestVBase != nullptr;
> > +}
> > +
> > llvm::Value *MicrosoftCXXABI::getVTableAddressPointInStructor(
> > CodeGenFunction &CGF, const CXXRecordDecl *VTableClass,
> BaseSubobject Base,
> > - const CXXRecordDecl *NearestVBase, bool &NeedsVirtualOffset) {
> > - NeedsVirtualOffset = (NearestVBase != nullptr);
> > -
> > - (void)getAddrOfVTable(VTableClass, Base.getBaseOffset());
> > - VFTableIdTy ID(VTableClass, Base.getBaseOffset());
> > - llvm::GlobalValue *VTableAddressPoint = VFTablesMap[ID];
> > + const CXXRecordDecl *NearestVBase) {
> > + llvm::Constant *VTableAddressPoint = getVTableAddressPoint(Base,
> VTableClass);
> > if (!VTableAddressPoint) {
> > assert(Base.getBase()->getNumVBases() &&
> >
> !getContext().getASTRecordLayout(Base.getBase()).hasOwnVFPtr());
> > @@ -1590,11 +1603,17 @@ static void mangleVFTableName(MicrosoftM
> > MangleContext.mangleCXXVFTable(RD, VFPtr->MangledPath, Out);
> > }
> >
> > -llvm::Constant *MicrosoftCXXABI::getVTableAddressPointForConstExpr(
> > - BaseSubobject Base, const CXXRecordDecl *VTableClass) {
> > +llvm::Constant *
> > +MicrosoftCXXABI::getVTableAddressPoint(BaseSubobject Base,
> > + const CXXRecordDecl
> *VTableClass) {
> > (void)getAddrOfVTable(VTableClass, Base.getBaseOffset());
> > VFTableIdTy ID(VTableClass, Base.getBaseOffset());
> > - llvm::GlobalValue *VFTable = VFTablesMap[ID];
> > + return VFTablesMap[ID];
> > +}
> > +
> > +llvm::Constant *MicrosoftCXXABI::getVTableAddressPointForConstExpr(
> > + BaseSubobject Base, const CXXRecordDecl *VTableClass) {
> > + llvm::Constant *VFTable = getVTableAddressPoint(Base, VTableClass);
> > assert(VFTable && "Couldn't find a vftable for the given base?");
> > return VFTable;
> > }
> > @@ -1604,6 +1623,7 @@ llvm::GlobalVariable *MicrosoftCXXABI::g
> > // getAddrOfVTable may return 0 if asked to get an address of a
> vtable which
> > // shouldn't be used in the given record type. We want to cache this
> result in
> > // VFTablesMap, thus a simple zero check is not sufficient.
> > +
> > VFTableIdTy ID(RD, VPtrOffset);
> > VTablesMapTy::iterator I;
> > bool Inserted;
> > @@ -1657,10 +1677,11 @@ llvm::GlobalVariable *MicrosoftCXXABI::g
> > if (llvm::GlobalValue *VFTable =
> > CGM.getModule().getNamedGlobal(VFTableName)) {
> > VFTablesMap[ID] = VFTable;
> > - return VTableAliasIsRequred
> > - ? cast<llvm::GlobalVariable>(
> > - cast<llvm::GlobalAlias>(VFTable)->getBaseObject())
> > - : cast<llvm::GlobalVariable>(VFTable);
> > + VTable = VTableAliasIsRequred
> > + ? cast<llvm::GlobalVariable>(
> > +
> cast<llvm::GlobalAlias>(VFTable)->getBaseObject())
> > + : cast<llvm::GlobalVariable>(VFTable);
> > + return VTable;
> > }
> >
> > uint64_t NumVTableSlots =
> >
> > Modified: cfe/trunk/test/CodeGen/available-externally-hidden.cpp
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/available-externally-hidden.cpp?rev=245264&r1=245263&r2=245264&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/test/CodeGen/available-externally-hidden.cpp (original)
> > +++ cfe/trunk/test/CodeGen/available-externally-hidden.cpp Mon Aug 17
> 22:52:00 2015
> > @@ -27,6 +27,6 @@ class TestSyncMessageFilter : public Syn
> > };
> >
> > int main() {
> > -TestSyncMessageFilter* f = new TestSyncMessageFilter;
> > + TestSyncMessageFilter *f = new TestSyncMessageFilter;
> > f->Send(new Message);
> > }
> >
> > Modified: cfe/trunk/test/CodeGenCXX/ctor-globalopt.cpp
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/ctor-globalopt.cpp?rev=245264&r1=245263&r2=245264&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/test/CodeGenCXX/ctor-globalopt.cpp (original)
> > +++ cfe/trunk/test/CodeGenCXX/ctor-globalopt.cpp Mon Aug 17 22:52:00 2015
> > @@ -1,7 +1,7 @@
> > // RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm -o - %s |
> FileCheck %s
> > -// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm -o - %s -O1 |
> FileCheck %s --check-prefix=O1
> > +// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm -o - %s -O2 |
> opt - -S -globalopt -o - | FileCheck %s --check-prefix=O1
> > // RUN: %clang_cc1 -triple %ms_abi_triple -emit-llvm -o - %s |
> FileCheck %s
> > -// RUN: %clang_cc1 -triple %ms_abi_triple -emit-llvm -o - %s -O1 |
> FileCheck %s --check-prefix=O1
> > +// RUN: %clang_cc1 -triple %ms_abi_triple -emit-llvm -o - %s -O2 | opt
> - -S -globalopt -o - | FileCheck %s --check-prefix=O1
> >
> > // Check that GlobalOpt can eliminate static constructors for simple
> implicit
> > // constructors. This is a targetted integration test to make sure that
> LLVM's
> >
> > Modified: cfe/trunk/test/CodeGenCXX/template-instantiation.cpp
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/template-instantiation.cpp?rev=245264&r1=245263&r2=245264&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/test/CodeGenCXX/template-instantiation.cpp (original)
> > +++ cfe/trunk/test/CodeGenCXX/template-instantiation.cpp Mon Aug 17
> 22:52:00 2015
> > @@ -1,5 +1,7 @@
> > // RUN: %clang_cc1 %s -O1 -disable-llvm-optzns
> -triple=x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s
> >
> > +// CHECK: @_ZTVN5test018stdio_sync_filebufIA4_iEE = linkonce_odr
> unnamed_addr constant
> > +
> > // CHECK: @_ZN7PR100011xE = global
> > // CHECK-NOT: @_ZN7PR100014kBarE = external global i32
> > //
> > @@ -12,7 +14,6 @@
> > // CHECK: @_ZN7PR100011SIiE3arrE = linkonce_odr global [3 x i32]
> > // CHECK-NOT: @_ZN7PR100011SIiE3arr2E = linkonce_odr global [3 x i32]A
> >
> > -// CHECK: @_ZTVN5test018stdio_sync_filebufIA4_iEE = linkonce_odr
> unnamed_addr constant
> >
> > // CHECK-NOT: _ZTVN5test31SIiEE
> > // CHECK-NOT: _ZTSN5test31SIiEE
> >
> > Modified: cfe/trunk/test/CodeGenCXX/thunks.cpp
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/thunks.cpp?rev=245264&r1=245263&r2=245264&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/test/CodeGenCXX/thunks.cpp (original)
> > +++ cfe/trunk/test/CodeGenCXX/thunks.cpp Mon Aug 17 22:52:00 2015
> > @@ -1,5 +1,9 @@
> > -// RUN: %clang_cc1 %s -triple=x86_64-pc-linux-gnu -munwind-tables
> -emit-llvm -o - | FileCheck %s
> > -// RUN: %clang_cc1 %s -triple=x86_64-pc-linux-gnu -munwind-tables
> -emit-llvm -o - -O1 -disable-llvm-optzns | FileCheck %s
> > +// RUN: %clang_cc1 %s -triple=x86_64-pc-linux-gnu -munwind-tables
> -emit-llvm -o %t
> > +// RUN: %clang_cc1 %s -triple=x86_64-pc-linux-gnu -munwind-tables
> -emit-llvm -o %t.opt -O1 -disable-llvm-optzns
> > +// RUN: FileCheck %s < %t
> > +// RUN: FileCheck %s < %t.opt
> > +// RUN: FileCheck --check-prefix=CHECK-NONOPT %s < %t
> > +// RUN: FileCheck --check-prefix=CHECK-OPT %s < %t.opt
> >
> > namespace Test1 {
> >
> > @@ -380,13 +384,25 @@ D::~D() {}
> >
> > /**** The following has to go at the end of the file ****/
> >
> > +// checking without opt
> > +// CHECK-NONOPT-LABEL: define internal void
> @_ZThn8_N6Test4B12_GLOBAL__N_11C1fEv(
> > +// CHECK-NONOPT-NOT: comdat
> > +
> > // This is from Test5:
> > -// CHECK-LABEL: define internal void
> @_ZThn8_N6Test4B12_GLOBAL__N_11C1fEv(
> > -// CHECK-NOT: comdat
> > -// CHECK-LABEL: define linkonce_odr void @_ZTv0_n24_N5Test51B1fEv
> > +// CHECK-NONOPT-LABEL: define linkonce_odr void @_ZTv0_n24_N5Test51B1fEv
> > +
> > +// This is from Test10:
> > +// CHECK-NONOPT-LABEL: define linkonce_odr void @_ZN6Test101C3fooEv
> > +// CHECK-NONOPT-LABEL: define linkonce_odr void @_ZThn8_N6Test101C3fooEv
> > +
> > +// Checking with opt
> > +// CHECK-OPT-LABEL: define internal void
> @_ZThn8_N6Test4B12_GLOBAL__N_11C1fEv(%"struct.Test4B::(anonymous
> namespace)::C"* %this) unnamed_addr #0 align 2
> >
> > // This is from Test10:
> > -// CHECK-LABEL: define linkonce_odr void @_ZN6Test101C3fooEv
> > -// CHECK-LABEL: define linkonce_odr void @_ZThn8_N6Test101C3fooEv
> > +// CHECK-OPT-LABEL: define linkonce_odr void @_ZN6Test101C3fooEv
> > +// CHECK-OPT-LABEL: define linkonce_odr void @_ZThn8_N6Test101C3fooEv
> > +
> > +// This is from Test5:
> > +// CHECK-OPT-LABEL: define linkonce_odr void @_ZTv0_n24_N5Test51B1fEv
> >
> > // CHECK: attributes [[NUW]] = { nounwind uwtable{{.*}} }
> >
> > Modified: cfe/trunk/test/CodeGenCXX/virtual-base-ctor.cpp
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/virtual-base-ctor.cpp?rev=245264&r1=245263&r2=245264&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/test/CodeGenCXX/virtual-base-ctor.cpp (original)
> > +++ cfe/trunk/test/CodeGenCXX/virtual-base-ctor.cpp Mon Aug 17 22:52:00
> 2015
> > @@ -1,4 +1,4 @@
> > -// RUN: %clang_cc1 %s -emit-llvm -triple %itanium_abi_triple -o - -O2 |
> FileCheck %s
> > +// RUN: %clang_cc1 %s -emit-llvm -triple %itanium_abi_triple -o - -O2 |
> opt - -S -globalopt -o - | FileCheck %s
> >
> > struct B;
> > extern B x;
> >
> > Added: cfe/trunk/test/CodeGenCXX/vtable-assume-load.cpp
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/vtable-assume-load.cpp?rev=245264&view=auto
> >
> ==============================================================================
> > --- cfe/trunk/test/CodeGenCXX/vtable-assume-load.cpp (added)
> > +++ cfe/trunk/test/CodeGenCXX/vtable-assume-load.cpp Mon Aug 17 22:52:00
> 2015
> > @@ -0,0 +1,172 @@
> > +// RUN: %clang_cc1 %s -triple x86_64-apple-darwin10 -emit-llvm -o %t.ll
> -O1 -disable-llvm-optzns -fms-extensions
> > +// RUN: %clang_cc1 %s -triple i686-pc-win32 -emit-llvm -o %t.ms.ll -O1
> -disable-llvm-optzns -fms-extensions
> > +
> > +// RUN: FileCheck --check-prefix=CHECK1 --input-file=%t.ll %s
> > +// RUN: FileCheck --check-prefix=CHECK2 --input-file=%t.ll %s
> > +// RUN: FileCheck --check-prefix=CHECK3 --input-file=%t.ll %s
> > +// RUN: FileCheck --check-prefix=CHECK4 --input-file=%t.ll %s
> > +// RUN: FileCheck --check-prefix=CHECK-MS --input-file=%t.ms.ll %s
> > +
> > +namespace test1 {
> > +
> > +struct A {
> > + A();
> > + virtual void foo();
> > +};
> > +
> > +struct B : A {
> > + virtual void foo();
> > +};
> > +
> > +void g(A *a) { a->foo(); }
> > +
> > +// CHECK1-LABEL: define void @_ZN5test14fooAEv()
> > +// CHECK1: call void @_ZN5test11AC1Ev(%"struct.test1::A"*
> > +// CHECK1: %[[VTABLE:.*]] = load i8**, i8*** %{{.*}}
> > +// CHECK1: %[[CMP:.*]] = icmp eq i8** %[[VTABLE]], getelementptr
> inbounds ([3 x i8*], [3 x i8*]* @_ZTVN5test11AE, i64 0, i64 2)
> > +// CHECK1: call void @llvm.assume(i1 %[[CMP]])
> > +// CHECK1-LABEL: }
> > +
> > +void fooA() {
> > + A a;
> > + g(&a);
> > +}
> > +
> > +// CHECK1-LABEL: define void @_ZN5test14fooBEv()
> > +// CHECK1: call void @_ZN5test11BC1Ev(%"struct.test1::B"* %{{.*}})
> > +// CHECK1: %[[VTABLE:.*]] = load i8**, i8*** %{{.*}}
> > +// CHECK1: %[[CMP:.*]] = icmp eq i8** %[[VTABLE]], getelementptr
> inbounds ([3 x i8*], [3 x i8*]* @_ZTVN5test11BE, i64 0, i64 2)
> > +// CHECK1: call void @llvm.assume(i1 %[[CMP]])
> > +// CHECK1-LABEL: }
> > +
> > +void fooB() {
> > + B b;
> > + g(&b);
> > +}
> > +// there should not be any assumes in the ctor that calls base ctor
> > +// CHECK1-LABEL: define linkonce_odr void
> @_ZN5test11BC2Ev(%"struct.test1::B"*
> > +// CHECK1-NOT: @llvm.assume(
> > +// CHECK1-LABEL: }
> > +}
> > +namespace test2 {
> > +struct A {
> > + A();
> > + virtual void foo();
> > +};
> > +
> > +struct B {
> > + B();
> > + virtual void bar();
> > +};
> > +
> > +struct C : A, B {
> > + C();
> > + virtual void foo();
> > +};
> > +void g(A *a) { a->foo(); }
> > +void h(B *b) { b->bar(); }
> > +
> > +// CHECK2-LABEL: define void @_ZN5test24testEv()
> > +// CHECK2: call void @_ZN5test21CC1Ev(%"struct.test2::C"*
> > +// CHECK2: %[[VTABLE:.*]] = load i8**, i8*** {{.*}}
> > +// CHECK2: %[[CMP:.*]] = icmp eq i8** %[[VTABLE]], getelementptr
> inbounds ([6 x i8*], [6 x i8*]* @_ZTVN5test21CE, i64 0, i64 2)
> > +// CHECK2: call void @llvm.assume(i1 %[[CMP]])
> > +
> > +// CHECK2: %[[V2:.*]] = bitcast %"struct.test2::C"* %{{.*}} to i8*
> > +// CHECK2: %[[ADD_PTR:.*]] = getelementptr inbounds i8, i8* %[[V2]],
> i64 8
> > +// CHECK2: %[[V3:.*]] = bitcast i8* %[[ADD_PTR]] to i8***
> > +// CHECK2: %[[VTABLE2:.*]] = load i8**, i8*** %[[V3]]
> > +// CHECK2: %[[CMP2:.*]] = icmp eq i8** %[[VTABLE2]], getelementptr
> inbounds ([6 x i8*], [6 x i8*]* @_ZTVN5test21CE, i64 0, i64 5)
> > +// CHECK2: call void @llvm.assume(i1 %[[CMP2]])
> > +
> > +// CHECK2: call void @_ZN5test21gEPNS_1AE(
> > +// CHECK2-LABEL: }
> > +
> > +void test() {
> > + C c;
> > + g(&c);
> > + h(&c);
> > +}
> > +}
> > +
> > +namespace test3 {
> > +struct A {
> > + A();
> > +};
> > +
> > +struct B : A {
> > + B();
> > + virtual void foo();
> > +};
> > +
> > +struct C : virtual A, B {
> > + C();
> > + virtual void foo();
> > +};
> > +void g(B *a) { a->foo(); }
> > +
> > +// CHECK3-LABEL: define void @_ZN5test34testEv()
> > +// CHECK3: call void @_ZN5test31CC1Ev(%"struct.test3::C"*
> > +// CHECK3: %[[CMP:.*]] = icmp eq i8** %{{.*}}, getelementptr inbounds
> ([4 x i8*], [4 x i8*]* @_ZTVN5test31CE, i64 0, i64 3)
> > +// CHECK3: call void @llvm.assume(i1 %[[CMP]])
> > +// CHECK3-LABLEL: }
> > +void test() {
> > + C c;
> > + g(&c);
> > +}
> > +} // test3
> > +
> > +namespace test4 {
> > +struct A {
> > + A();
> > + virtual void foo();
> > +};
> > +
> > +struct B : virtual A {
> > + B();
> > + virtual void foo();
> > +};
> > +struct C : B {
> > + C();
> > + virtual void foo();
> > +};
> > +
> > +void g(C *c) { c->foo(); }
> > +
> > +// CHECK4-LABEL: define void @_ZN5test44testEv()
> > +// CHECK4: call void @_ZN5test41CC1Ev(%"struct.test4::C"*
> > +// CHECK4: %[[VTABLE:.*]] = load i8**, i8*** %{{.*}}
> > +// CHECK4: %[[CMP:.*]] = icmp eq i8** %[[VTABLE]], getelementptr
> inbounds ([5 x i8*], [5 x i8*]* @_ZTVN5test41CE, i64 0, i64 4)
> > +// CHECK4: call void @llvm.assume(i1 %[[CMP]]
> > +
> > +// CHECK4: %[[VTABLE2:.*]] = load i8**, i8*** %{{.*}}
> > +// CHECK4: %[[CMP2:.*]] = icmp eq i8** %[[VTABLE2]], getelementptr
> inbounds ([5 x i8*], [5 x i8*]* @_ZTVN5test41CE, i64 0, i64 4)
> > +// CHECK4: call void @llvm.assume(i1 %[[CMP2]])
> > +// CHECK4-LABEL: }
> > +
> > +void test() {
> > + C c;
> > + g(&c);
> > +}
> > +} // test4
> > +
> > +namespace test5 {
> > +
> > +struct __declspec(novtable) S {
> > + virtual void foo();
> > +};
> > +
> > +void g(S &s) { s.foo(); }
> > +
> > +// if struct has novtable specifier, then we can't generate assumes
> > +// CHECK-MS-LABEL: define void @"\01?test at test5@@YAXXZ"()
> > +// CHECK-MS: call x86_thiscallcc %"struct.test5::S"* @"\01??0S at test5
> @@QAE at XZ"(
> > +// CHECK-MS-NOT: @llvm.assume
> > +// CHECK-MS-LABEL: }
> > +
> > +void test() {
> > + S s;
> > + g(s);
> > +}
> > +
> > +} // test5
> >
> > Modified: cfe/trunk/test/CodeGenCXX/vtable-available-externally.cpp
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/vtable-available-externally.cpp?rev=245264&r1=245263&r2=245264&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/test/CodeGenCXX/vtable-available-externally.cpp (original)
> > +++ cfe/trunk/test/CodeGenCXX/vtable-available-externally.cpp Mon Aug 17
> 22:52:00 2015
> > @@ -182,8 +182,8 @@ void f() {
> > namespace Test9 {
> > // all virtual functions are outline, so we can assume that it will
> > // be generated in translation unit where foo is defined
> > -// CHECK-TEST9: @_ZTVN5Test91AE = available_externally unnamed_addr
> constant
> > -// CHECK-TEST9: @_ZTVN5Test91BE = available_externally unnamed_addr
> constant
> > +// CHECK-TEST9-DAG: @_ZTVN5Test91AE = available_externally unnamed_addr
> constant
> > +// CHECK-TEST9-DAG: @_ZTVN5Test91BE = available_externally unnamed_addr
> constant
> > struct A {
> > virtual void foo();
> > virtual void bar();
> > @@ -206,7 +206,7 @@ void g() {
> > namespace Test10 {
> >
> > // because A's key function is defined here, vtable is generated in
> this TU
> > -// CHECK-TEST10: @_ZTVN6Test101AE = unnamed_addr constant
> > +// CHECK-TEST10-DAG: @_ZTVN6Test101AE = unnamed_addr constant
> > struct A {
> > virtual void foo();
> > virtual void bar();
> > @@ -214,14 +214,14 @@ struct A {
> > void A::foo() {}
> >
> > // Because key function is inline we will generate vtable as
> linkonce_odr
> > -// CHECK-TEST10: @_ZTVN6Test101DE = linkonce_odr unnamed_addr constant
> > +// CHECK-TEST10-DAG: @_ZTVN6Test101DE = linkonce_odr unnamed_addr
> constant
> > struct D : A {
> > void bar();
> > };
> > inline void D::bar() {}
> >
> > // because B has outline key function then we can refer to
> > -// CHECK-TEST10: @_ZTVN6Test101BE = available_externally unnamed_addr
> constant
> > +// CHECK-TEST10-DAG: @_ZTVN6Test101BE = available_externally
> unnamed_addr constant
> > struct B : A {
> > void foo();
> > void bar();
> > @@ -230,7 +230,7 @@ struct B : A {
> > // C's key function (car) is outline, but C has inline virtual function
> so we
> > // can't guarantee that we will be able to refer to bar from name
> > // so (at the moment) we can't emit vtable available_externally
> > -// CHECK-TEST10: @_ZTVN6Test101CE = external unnamed_addr constant
> > +// CHECK-TEST10-DAG: @_ZTVN6Test101CE = external unnamed_addr constant
> > struct C : A {
> > void bar() {} // defined in body - not key function
> > virtual inline void gar(); // inline in body - not key function
> > @@ -238,7 +238,7 @@ struct C : A {
> > };
> >
> > // no key function, vtable will be generated everywhere it will be used
> > -// CHECK-TEST10: @_ZTVN6Test101EE = linkonce_odr unnamed_addr constant
> > +// CHECK-TEST10-DAG: @_ZTVN6Test101EE = linkonce_odr unnamed_addr
> constant
> > struct E : A {};
> >
> > void g(A& a) {
> >
> >
> > _______________________________________________
> > cfe-commits mailing list
> > cfe-commits at lists.llvm.org
> > http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20150817/aceb0229/attachment-0001.html>
More information about the cfe-commits
mailing list