Piotr Padlewski via cfe-commits <cfe-commits@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@test5@@YAXXZ"()
> +// CHECK-MS: call x86_thiscallcc %"struct.test5::S"* @"\01??0S@test5@@QAE@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@lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
