r211473 - Revert "Revert r211402 (and r211408, r211410), "CodeGen: Refactor dynamic_cast and typeid" It crashes msvc codegen in clang/test/SemaCXX/undefined-internal.cpp."

David Majnemer david.majnemer at gmail.com
Mon Jun 23 10:40:21 PDT 2014


On Sun, Jun 22, 2014 at 10:17 PM, David Blaikie <dblaikie at gmail.com> wrote:

> On Sun, Jun 22, 2014 at 2:39 PM, David Majnemer
> <david.majnemer at gmail.com> wrote:
> > Below is a reconstruction of the delta between the original commit,
> r211402,
> > and the ultimate commit, r211473.
> >
> > The difference boiled down to whether or not the adjusted 'this' pointer
> was
> > calculated via getPolymorphicOffset or performBaseAdjustment.
> > getPolymorphicOffset assumes that there is some base in the most derived
> > type which is polymorphic while performBaseAdjustment first checks to
> see if
> > the most derived type has it's own virtual function-table pointer.
>
> Thanks for the details - nice to include this in the commit message next
> time.
>
> Did you add portable test coverage for this? (so that the test would
> fail for any developer on any platform (ie: a test with a fixed triple
> for the problematic platform - and that does more than "does not
> crash" in whatever way is relevant for this test - since the original
> test that failed was in SemaCXX and the other tests for this code were
> in CodeGenCXX, I guess there might be some missing result coverage for
> the particular functionality this patch implements that was only being
> incidentally covered by the SemaCXX test case?)
>

Done in r211505.


>
> >
> > $ git diff a73161..5d2297 lib/CodeGen
> > diff --git a/lib/CodeGen/MicrosoftCXXABI.cpp
> > b/lib/CodeGen/MicrosoftCXXABI.cpp
> > index f3c79ef..e19904f 100644
> > --- a/lib/CodeGen/MicrosoftCXXABI.cpp
> > +++ b/lib/CodeGen/MicrosoftCXXABI.cpp
> > @@ -548,10 +548,13 @@ llvm::Value
> > *MicrosoftCXXABI::EmitTypeid(CodeGenFunction &CGF,
> >                                           QualType SrcRecordTy,
> >                                           llvm::Value *ThisPtr,
> >                                           llvm::Type *StdTypeInfoPtrTy) {
> > -  llvm::Value *Offset;
> > -  std::tie(ThisPtr, Offset) = performBaseAdjustment(CGF, ThisPtr,
> > SrcRecordTy);
> > +  const CXXRecordDecl *RD = SrcRecordTy->getAsCXXRecordDecl();
> > +  llvm::Value *CastPtr = CGF.Builder.CreateBitCast(ThisPtr,
> CGF.Int8PtrTy);
> > +  llvm::Value *AdjustedThisPtr = CGF.Builder.CreateInBoundsGEP(
> > +      CastPtr, getPolymorphicOffset(CGF, RD, CastPtr));
> >    return CGF.Builder.CreateBitCast(
> > -      emitRTtypeidCall(CGF, ThisPtr).getInstruction(),
> StdTypeInfoPtrTy);
> > +      emitRTtypeidCall(CGF, AdjustedThisPtr).getInstruction(),
> > +      StdTypeInfoPtrTy);
> >  }
> >
> >  bool MicrosoftCXXABI::shouldDynamicCastCallBeNullChecked(bool SrcIsPtr,
> >
> >
> > On Sun, Jun 22, 2014 at 8:59 PM, David Blaikie <dblaikie at gmail.com>
> wrote:
> >>
> >> I'm a little confused about what was reverted/committed here. If this
> was
> >> a recommit after a revert due to breakage it'd be nice to understand
> how the
> >> breakage was addressed, for example.
> >>
> >> On Jun 22, 2014 12:19 PM, "David Majnemer" <david.majnemer at gmail.com>
> >> wrote:
> >>>
> >>> Author: majnemer
> >>> Date: Sun Jun 22 14:05:33 2014
> >>> New Revision: 211473
> >>>
> >>> URL: http://llvm.org/viewvc/llvm-project?rev=211473&view=rev
> >>> Log:
> >>> Revert "Revert r211402 (and r211408,r211410), "CodeGen: Refactor
> >>> dynamic_cast and typeid" It crashes msvc codegen in
> >>> clang/test/SemaCXX/undefined-internal.cpp."
> >>>
> >>> This reverts commit r211467 which reverted r211408,r211410, it caused
> >>> crashes in test/SemaCXX/undefined-internal.cpp for i686-win32 targets.
> >>>
> >>> Modified:
> >>>     cfe/trunk/lib/CodeGen/CGCXXABI.h
> >>>     cfe/trunk/lib/CodeGen/CGExprCXX.cpp
> >>>     cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp
> >>>     cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp
> >>>     cfe/trunk/test/CodeGenCXX/microsoft-abi-dynamic-cast.cpp
> >>>     cfe/trunk/test/CodeGenCXX/microsoft-abi-typeid.cpp
> >>>
> >>> Modified: cfe/trunk/lib/CodeGen/CGCXXABI.h
> >>> URL:
> >>>
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCXXABI.h?rev=211473&r1=211472&r2=211473&view=diff
> >>>
> >>>
> ==============================================================================
> >>> --- cfe/trunk/lib/CodeGen/CGCXXABI.h (original)
> >>> +++ cfe/trunk/lib/CodeGen/CGCXXABI.h Sun Jun 22 14:05:33 2014
> >>> @@ -207,6 +207,28 @@ public:
> >>>                                                llvm::Value *ptr,
> >>>                                                QualType type) = 0;
> >>>
> >>> +  virtual bool shouldTypeidBeNullChecked(bool IsDeref,
> >>> +                                         QualType SrcRecordTy) = 0;
> >>> +  virtual void EmitBadTypeidCall(CodeGenFunction &CGF) = 0;
> >>> +  virtual llvm::Value *EmitTypeid(CodeGenFunction &CGF, QualType
> >>> SrcRecordTy,
> >>> +                                  llvm::Value *ThisPtr,
> >>> +                                  llvm::Type *StdTypeInfoPtrTy) = 0;
> >>> +
> >>> +  virtual bool shouldDynamicCastCallBeNullChecked(bool SrcIsPtr,
> >>> +                                                  QualType
> SrcRecordTy)
> >>> = 0;
> >>> +
> >>> +  virtual llvm::Value *
> >>> +  EmitDynamicCastCall(CodeGenFunction &CGF, llvm::Value *Value,
> >>> +                      QualType SrcRecordTy, QualType DestTy,
> >>> +                      QualType DestRecordTy, llvm::BasicBlock
> *CastEnd)
> >>> = 0;
> >>> +
> >>> +  virtual llvm::Value *EmitDynamicCastToVoid(CodeGenFunction &CGF,
> >>> +                                             llvm::Value *Value,
> >>> +                                             QualType SrcRecordTy,
> >>> +                                             QualType DestTy) = 0;
> >>> +
> >>> +  virtual bool EmitBadCastCall(CodeGenFunction &CGF) = 0;
> >>> +
> >>>    virtual llvm::Value *GetVirtualBaseClassOffset(CodeGenFunction &CGF,
> >>>                                                   llvm::Value *This,
> >>>                                                   const CXXRecordDecl
> >>> *ClassDecl,
> >>>
> >>> Modified: cfe/trunk/lib/CodeGen/CGExprCXX.cpp
> >>> URL:
> >>>
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprCXX.cpp?rev=211473&r1=211472&r2=211473&view=diff
> >>>
> >>>
> ==============================================================================
> >>> --- cfe/trunk/lib/CodeGen/CGExprCXX.cpp (original)
> >>> +++ cfe/trunk/lib/CodeGen/CGExprCXX.cpp Sun Jun 22 14:05:33 2014
> >>> @@ -1615,98 +1615,36 @@ void CodeGenFunction::EmitCXXDeleteExpr(
> >>>    EmitBlock(DeleteEnd);
> >>>  }
> >>>
> >>> -static llvm::Constant *getBadTypeidFn(CodeGenFunction &CGF) {
> >>> -  // void __cxa_bad_typeid();
> >>> -  llvm::FunctionType *FTy = llvm::FunctionType::get(CGF.VoidTy,
> false);
> >>> -
> >>> -  return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_bad_typeid");
> >>> -}
> >>> -
> >>> -static void EmitBadTypeidCall(CodeGenFunction &CGF) {
> >>> -  llvm::Value *Fn = getBadTypeidFn(CGF);
> >>> -  CGF.EmitRuntimeCallOrInvoke(Fn).setDoesNotReturn();
> >>> -  CGF.Builder.CreateUnreachable();
> >>> -}
> >>> -
> >>> -/// \brief Gets the offset to the virtual base that contains the vfptr
> >>> for
> >>> -/// MS-ABI polymorphic types.
> >>> -static llvm::Value *getPolymorphicOffset(CodeGenFunction &CGF,
> >>> -                                         const CXXRecordDecl *RD,
> >>> -                                         llvm::Value *Value) {
> >>> -  const ASTContext &Context = RD->getASTContext();
> >>> -  for (const CXXBaseSpecifier &Base : RD->vbases())
> >>> -    if
> (Context.getASTRecordLayout(Base.getType()->getAsCXXRecordDecl())
> >>> -            .hasExtendableVFPtr())
> >>> -      return CGF.CGM.getCXXABI().GetVirtualBaseClassOffset(
> >>> -          CGF, Value, RD, Base.getType()->getAsCXXRecordDecl());
> >>> -  llvm_unreachable("One of our vbases should be polymorphic.");
> >>> -}
> >>> -
> >>> -static llvm::Value *emitRTtypeidCall(CodeGenFunction &CGF,
> >>> -                                     llvm::Value *Argument) {
> >>> -  llvm::Type *ArgTypes[] = {CGF.Int8PtrTy};
> >>> -  llvm::Constant *Function = CGF.CGM.CreateRuntimeFunction(
> >>> -      llvm::FunctionType::get(CGF.Int8PtrTy, ArgTypes, false),
> >>> "__RTtypeid");
> >>> -  llvm::Value *Args[] = {Argument};
> >>> -  return CGF.EmitRuntimeCall(Function, Args);
> >>> -}
> >>> -
> >>>  static llvm::Value *EmitTypeidFromVTable(CodeGenFunction &CGF, const
> >>> Expr *E,
> >>>                                           llvm::Type
> *StdTypeInfoPtrTy) {
> >>>    // Get the vtable pointer.
> >>>    llvm::Value *ThisPtr = CGF.EmitLValue(E).getAddress();
> >>>
> >>> -  if (CGF.getTarget().getCXXABI().isMicrosoft()) {
> >>> -    llvm::Value *CastPtr = CGF.Builder.CreateBitCast(ThisPtr,
> >>> CGF.Int8PtrTy);
> >>> -    const CXXRecordDecl *RD = E->getType()->getAsCXXRecordDecl();
> >>> -    if (CGF.getContext().getASTRecordLayout(RD).hasExtendableVFPtr())
> >>> -      return CGF.Builder.CreateBitCast(emitRTtypeidCall(CGF, CastPtr),
> >>> -                                       StdTypeInfoPtrTy);
> >>> -    llvm::BasicBlock *EntryBlock = CGF.Builder.GetInsertBlock();
> >>> -    llvm::BasicBlock *AdjustBlock =
> >>> CGF.createBasicBlock("type_id.valid");
> >>> -    llvm::BasicBlock *ExitBlock =
> CGF.createBasicBlock("type_id.call");
> >>> -    CGF.Builder.CreateCondBr(CGF.Builder.CreateIsNull(CastPtr),
> >>> ExitBlock,
> >>> -                             AdjustBlock);
> >>> -    // Emit the call block and code for it.
> >>> -    CGF.EmitBlock(AdjustBlock);
> >>> -    llvm::Value *AdjustedThisPtr = CGF.Builder.CreateInBoundsGEP(
> >>> -        CastPtr, getPolymorphicOffset(CGF, RD, CastPtr));
> >>> -    // Emit the call block and the phi nodes for it.
> >>> -    CGF.EmitBlock(ExitBlock);
> >>> -    llvm::PHINode *ValuePHI = CGF.Builder.CreatePHI(CGF.Int8PtrTy, 2);
> >>> -    ValuePHI->addIncoming(AdjustedThisPtr, AdjustBlock);
> >>> -    ValuePHI->addIncoming(llvm::Constant::getNullValue(CGF.Int8PtrTy),
> >>> -                          EntryBlock);
> >>> -    return CGF.Builder.CreateBitCast(emitRTtypeidCall(CGF, ValuePHI),
> >>> -                                     StdTypeInfoPtrTy);
> >>> -  }
> >>> -
> >>>    // C++ [expr.typeid]p2:
> >>>    //   If the glvalue expression is obtained by applying the unary *
> >>> operator to
> >>>    //   a pointer and the pointer is a null pointer value, the typeid
> >>> expression
> >>>    //   throws the std::bad_typeid exception.
> >>> -  if (const UnaryOperator *UO =
> >>> dyn_cast<UnaryOperator>(E->IgnoreParens())) {
> >>> -    if (UO->getOpcode() == UO_Deref) {
> >>> -      llvm::BasicBlock *BadTypeidBlock =
> >>> +  bool IsDeref = false;
> >>> +  if (const UnaryOperator *UO =
> >>> dyn_cast<UnaryOperator>(E->IgnoreParens()))
> >>> +    if (UO->getOpcode() == UO_Deref)
> >>> +      IsDeref = true;
> >>> +
> >>> +  QualType SrcRecordTy = E->getType();
> >>> +  if (CGF.CGM.getCXXABI().shouldTypeidBeNullChecked(IsDeref,
> >>> SrcRecordTy)) {
> >>> +    llvm::BasicBlock *BadTypeidBlock =
> >>>          CGF.createBasicBlock("typeid.bad_typeid");
> >>> -      llvm::BasicBlock *EndBlock =
> >>> -        CGF.createBasicBlock("typeid.end");
> >>> +    llvm::BasicBlock *EndBlock = CGF.createBasicBlock("typeid.end");
> >>>
> >>> -      llvm::Value *IsNull = CGF.Builder.CreateIsNull(ThisPtr);
> >>> -      CGF.Builder.CreateCondBr(IsNull, BadTypeidBlock, EndBlock);
> >>> +    llvm::Value *IsNull = CGF.Builder.CreateIsNull(ThisPtr);
> >>> +    CGF.Builder.CreateCondBr(IsNull, BadTypeidBlock, EndBlock);
> >>>
> >>> -      CGF.EmitBlock(BadTypeidBlock);
> >>> -      EmitBadTypeidCall(CGF);
> >>> -      CGF.EmitBlock(EndBlock);
> >>> -    }
> >>> +    CGF.EmitBlock(BadTypeidBlock);
> >>> +    CGF.CGM.getCXXABI().EmitBadTypeidCall(CGF);
> >>> +    CGF.EmitBlock(EndBlock);
> >>>    }
> >>>
> >>> -  llvm::Value *Value = CGF.GetVTablePtr(ThisPtr,
> >>> -
> >>> StdTypeInfoPtrTy->getPointerTo());
> >>> -
> >>> -  // Load the type info.
> >>> -  Value = CGF.Builder.CreateConstInBoundsGEP1_64(Value, -1ULL);
> >>> -  return CGF.Builder.CreateLoad(Value);
> >>> +  return CGF.CGM.getCXXABI().EmitTypeid(CGF, SrcRecordTy, ThisPtr,
> >>> +                                        StdTypeInfoPtrTy);
> >>>  }
> >>>
> >>>  llvm::Value *CodeGenFunction::EmitCXXTypeidExpr(const CXXTypeidExpr
> *E)
> >>> {
> >>> @@ -1733,173 +1671,6 @@ llvm::Value *CodeGenFunction::EmitCXXTyp
> >>>                                 StdTypeInfoPtrTy);
> >>>  }
> >>>
> >>> -static llvm::Constant *getItaniumDynamicCastFn(CodeGenFunction &CGF) {
> >>> -  // void *__dynamic_cast(const void *sub,
> >>> -  //                      const abi::__class_type_info *src,
> >>> -  //                      const abi::__class_type_info *dst,
> >>> -  //                      std::ptrdiff_t src2dst_offset);
> >>> -
> >>> -  llvm::Type *Int8PtrTy = CGF.Int8PtrTy;
> >>> -  llvm::Type *PtrDiffTy =
> >>> -    CGF.ConvertType(CGF.getContext().getPointerDiffType());
> >>> -
> >>> -  llvm::Type *Args[4] = { Int8PtrTy, Int8PtrTy, Int8PtrTy, PtrDiffTy
> };
> >>> -
> >>> -  llvm::FunctionType *FTy = llvm::FunctionType::get(Int8PtrTy, Args,
> >>> false);
> >>> -
> >>> -  // Mark the function as nounwind readonly.
> >>> -  llvm::Attribute::AttrKind FuncAttrs[] = { llvm::Attribute::NoUnwind,
> >>> -                                            llvm::Attribute::ReadOnly
> };
> >>> -  llvm::AttributeSet Attrs = llvm::AttributeSet::get(
> >>> -      CGF.getLLVMContext(), llvm::AttributeSet::FunctionIndex,
> >>> FuncAttrs);
> >>> -
> >>> -  return CGF.CGM.CreateRuntimeFunction(FTy, "__dynamic_cast", Attrs);
> >>> -}
> >>> -
> >>> -static llvm::Constant *getBadCastFn(CodeGenFunction &CGF) {
> >>> -  // void __cxa_bad_cast();
> >>> -  llvm::FunctionType *FTy = llvm::FunctionType::get(CGF.VoidTy,
> false);
> >>> -  return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_bad_cast");
> >>> -}
> >>> -
> >>> -static void EmitBadCastCall(CodeGenFunction &CGF) {
> >>> -  llvm::Value *Fn = getBadCastFn(CGF);
> >>> -  CGF.EmitRuntimeCallOrInvoke(Fn).setDoesNotReturn();
> >>> -  CGF.Builder.CreateUnreachable();
> >>> -}
> >>> -
> >>> -/// \brief Compute the src2dst_offset hint as described in the
> >>> -/// Itanium C++ ABI [2.9.7]
> >>> -static CharUnits computeOffsetHint(ASTContext &Context,
> >>> -                                   const CXXRecordDecl *Src,
> >>> -                                   const CXXRecordDecl *Dst) {
> >>> -  CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
> >>> -                     /*DetectVirtual=*/false);
> >>> -
> >>> -  // If Dst is not derived from Src we can skip the whole computation
> >>> below and
> >>> -  // return that Src is not a public base of Dst.  Record all
> >>> inheritance paths.
> >>> -  if (!Dst->isDerivedFrom(Src, Paths))
> >>> -    return CharUnits::fromQuantity(-2ULL);
> >>> -
> >>> -  unsigned NumPublicPaths = 0;
> >>> -  CharUnits Offset;
> >>> -
> >>> -  // Now walk all possible inheritance paths.
> >>> -  for (CXXBasePaths::paths_iterator I = Paths.begin(), E =
> Paths.end();
> >>> -       I != E; ++I) {
> >>> -    if (I->Access != AS_public) // Ignore non-public inheritance.
> >>> -      continue;
> >>> -
> >>> -    ++NumPublicPaths;
> >>> -
> >>> -    for (CXXBasePath::iterator J = I->begin(), JE = I->end(); J != JE;
> >>> ++J) {
> >>> -      // If the path contains a virtual base class we can't give any
> >>> hint.
> >>> -      // -1: no hint.
> >>> -      if (J->Base->isVirtual())
> >>> -        return CharUnits::fromQuantity(-1ULL);
> >>> -
> >>> -      if (NumPublicPaths > 1) // Won't use offsets, skip computation.
> >>> -        continue;
> >>> -
> >>> -      // Accumulate the base class offsets.
> >>> -      const ASTRecordLayout &L = Context.getASTRecordLayout(J->Class);
> >>> -      Offset +=
> >>> L.getBaseClassOffset(J->Base->getType()->getAsCXXRecordDecl());
> >>> -    }
> >>> -  }
> >>> -
> >>> -  // -2: Src is not a public base of Dst.
> >>> -  if (NumPublicPaths == 0)
> >>> -    return CharUnits::fromQuantity(-2ULL);
> >>> -
> >>> -  // -3: Src is a multiple public base type but never a virtual base
> >>> type.
> >>> -  if (NumPublicPaths > 1)
> >>> -    return CharUnits::fromQuantity(-3ULL);
> >>> -
> >>> -  // Otherwise, the Src type is a unique public nonvirtual base type
> of
> >>> Dst.
> >>> -  // Return the offset of Src from the origin of Dst.
> >>> -  return Offset;
> >>> -}
> >>> -
> >>> -static llvm::Value *
> >>> -EmitItaniumDynamicCastCall(CodeGenFunction &CGF, llvm::Value *Value,
> >>> -                    QualType SrcTy, QualType DestTy,
> >>> -                    llvm::BasicBlock *CastEnd) {
> >>> -  llvm::Type *PtrDiffLTy =
> >>> -    CGF.ConvertType(CGF.getContext().getPointerDiffType());
> >>> -  llvm::Type *DestLTy = CGF.ConvertType(DestTy);
> >>> -
> >>> -  if (const PointerType *PTy = DestTy->getAs<PointerType>()) {
> >>> -    if (PTy->getPointeeType()->isVoidType()) {
> >>> -      // C++ [expr.dynamic.cast]p7:
> >>> -      //   If T is "pointer to cv void," then the result is a pointer
> to
> >>> the
> >>> -      //   most derived object pointed to by v.
> >>> -
> >>> -      // Get the vtable pointer.
> >>> -      llvm::Value *VTable = CGF.GetVTablePtr(Value,
> >>> PtrDiffLTy->getPointerTo());
> >>> -
> >>> -      // Get the offset-to-top from the vtable.
> >>> -      llvm::Value *OffsetToTop =
> >>> -        CGF.Builder.CreateConstInBoundsGEP1_64(VTable, -2ULL);
> >>> -      OffsetToTop = CGF.Builder.CreateLoad(OffsetToTop,
> >>> "offset.to.top");
> >>> -
> >>> -      // Finally, add the offset to the pointer.
> >>> -      Value = CGF.EmitCastToVoidPtr(Value);
> >>> -      Value = CGF.Builder.CreateInBoundsGEP(Value, OffsetToTop);
> >>> -
> >>> -      return CGF.Builder.CreateBitCast(Value, DestLTy);
> >>> -    }
> >>> -  }
> >>> -
> >>> -  QualType SrcRecordTy;
> >>> -  QualType DestRecordTy;
> >>> -
> >>> -  if (const PointerType *DestPTy = DestTy->getAs<PointerType>()) {
> >>> -    SrcRecordTy = SrcTy->castAs<PointerType>()->getPointeeType();
> >>> -    DestRecordTy = DestPTy->getPointeeType();
> >>> -  } else {
> >>> -    SrcRecordTy = SrcTy;
> >>> -    DestRecordTy = DestTy->castAs<ReferenceType>()->getPointeeType();
> >>> -  }
> >>> -
> >>> -  assert(SrcRecordTy->isRecordType() && "source type must be a record
> >>> type!");
> >>> -  assert(DestRecordTy->isRecordType() && "dest type must be a record
> >>> type!");
> >>> -
> >>> -  llvm::Value *SrcRTTI =
> >>> -    CGF.CGM.GetAddrOfRTTIDescriptor(SrcRecordTy.getUnqualifiedType());
> >>> -  llvm::Value *DestRTTI =
> >>> -
>  CGF.CGM.GetAddrOfRTTIDescriptor(DestRecordTy.getUnqualifiedType());
> >>> -
> >>> -  // Compute the offset hint.
> >>> -  const CXXRecordDecl *SrcDecl = SrcRecordTy->getAsCXXRecordDecl();
> >>> -  const CXXRecordDecl *DestDecl = DestRecordTy->getAsCXXRecordDecl();
> >>> -  llvm::Value *OffsetHint =
> >>> -    llvm::ConstantInt::get(PtrDiffLTy,
> >>> -                           computeOffsetHint(CGF.getContext(),
> SrcDecl,
> >>> -                                             DestDecl).getQuantity());
> >>> -
> >>> -  // Emit the call to __dynamic_cast.
> >>> -  Value = CGF.EmitCastToVoidPtr(Value);
> >>> -
> >>> -  llvm::Value *args[] = { Value, SrcRTTI, DestRTTI, OffsetHint };
> >>> -  Value = CGF.EmitNounwindRuntimeCall(getItaniumDynamicCastFn(CGF),
> >>> args);
> >>> -  Value = CGF.Builder.CreateBitCast(Value, DestLTy);
> >>> -
> >>> -  /// C++ [expr.dynamic.cast]p9:
> >>> -  ///   A failed cast to reference type throws std::bad_cast
> >>> -  if (DestTy->isReferenceType()) {
> >>> -    llvm::BasicBlock *BadCastBlock =
> >>> -      CGF.createBasicBlock("dynamic_cast.bad_cast");
> >>> -
> >>> -    llvm::Value *IsNull = CGF.Builder.CreateIsNull(Value);
> >>> -    CGF.Builder.CreateCondBr(IsNull, BadCastBlock, CastEnd);
> >>> -
> >>> -    CGF.EmitBlock(BadCastBlock);
> >>> -    EmitBadCastCall(CGF);
> >>> -  }
> >>> -
> >>> -  return Value;
> >>> -}
> >>> -
> >>>  static llvm::Value *EmitDynamicCastToNull(CodeGenFunction &CGF,
> >>>                                            QualType DestTy) {
> >>>    llvm::Type *DestLTy = CGF.ConvertType(DestTy);
> >>> @@ -1908,142 +1679,49 @@ static llvm::Value *EmitDynamicCastToNul
> >>>
> >>>    /// C++ [expr.dynamic.cast]p9:
> >>>    ///   A failed cast to reference type throws std::bad_cast
> >>> -  EmitBadCastCall(CGF);
> >>> +  if (!CGF.CGM.getCXXABI().EmitBadCastCall(CGF))
> >>> +    return nullptr;
> >>>
> >>>    CGF.EmitBlock(CGF.createBasicBlock("dynamic_cast.end"));
> >>>    return llvm::UndefValue::get(DestLTy);
> >>>  }
> >>>
> >>> -namespace {
> >>> -struct MSDynamicCastBuilder {
> >>> -  MSDynamicCastBuilder(CodeGenFunction &CGF, const CXXDynamicCastExpr
> >>> *DCE);
> >>> -  llvm::Value *emitDynamicCastCall(llvm::Value *Value);
> >>> -  llvm::Value *emitDynamicCast(llvm::Value *Value);
> >>> -
> >>> -  CodeGenFunction &CGF;
> >>> -  CGBuilderTy &Builder;
> >>> -  llvm::PointerType *Int8PtrTy;
> >>> -  QualType SrcTy, DstTy;
> >>> -  const CXXRecordDecl *SrcDecl;
> >>> -  bool IsPtrCast, IsCastToVoid, IsCastOfNull;
> >>> -};
> >>> -} // namespace
> >>> -
> >>> -MSDynamicCastBuilder::MSDynamicCastBuilder(CodeGenFunction &CGF,
> >>> -                                           const CXXDynamicCastExpr
> >>> *DCE)
> >>> -    : CGF(CGF), Builder(CGF.Builder), Int8PtrTy(CGF.Int8PtrTy),
> >>> -      SrcDecl(nullptr) {
> >>> -  DstTy = DCE->getTypeAsWritten();
> >>> -  IsPtrCast = DstTy->isPointerType();
> >>> -  // Get the PointeeTypes.  After this point the original types are
> not
> >>> used.
> >>> -  DstTy = IsPtrCast ? DstTy->castAs<PointerType>()->getPointeeType()
> >>> -                    :
> DstTy->castAs<ReferenceType>()->getPointeeType();
> >>> -  IsCastToVoid = DstTy->isVoidType();
> >>> -  IsCastOfNull = DCE->isAlwaysNull();
> >>> -  if (IsCastOfNull)
> >>> -    return;
> >>> -  SrcTy = DCE->getSubExpr()->getType();
> >>> -  SrcTy = IsPtrCast ? SrcTy->castAs<PointerType>()->getPointeeType() :
> >>> SrcTy;
> >>> -  SrcDecl = SrcTy->getAsCXXRecordDecl();
> >>> -  // If we don't need a base adjustment, we don't need a SrcDecl so
> >>> clear it
> >>> -  // here.  Later we use the existence of the SrcDecl to determine the
> >>> need for
> >>> -  // a base adjustment.
> >>> -  if
> (CGF.getContext().getASTRecordLayout(SrcDecl).hasExtendableVFPtr())
> >>> -    SrcDecl = nullptr;
> >>> -}
> >>> -
> >>> -llvm::Value *MSDynamicCastBuilder::emitDynamicCastCall(llvm::Value
> >>> *Value) {
> >>> -  llvm::IntegerType *Int32Ty = CGF.Int32Ty;
> >>> -  llvm::Value *Offset = llvm::ConstantInt::get(Int32Ty, 0);
> >>> -  Value = Builder.CreateBitCast(Value, Int8PtrTy);
> >>> -  // If we need to perform a base adjustment, do it here.
> >>> -  if (SrcDecl) {
> >>> -    Offset = getPolymorphicOffset(CGF, SrcDecl, Value);
> >>> -    Value = Builder.CreateInBoundsGEP(Value, Offset);
> >>> -    Offset = Builder.CreateTrunc(Offset, Int32Ty);
> >>> -  }
> >>> -  if (IsCastToVoid) {
> >>> -    // PVOID __RTCastToVoid(
> >>> -    //   PVOID inptr)
> >>> -    llvm::Type *ArgTypes[] = {Int8PtrTy};
> >>> -    llvm::Constant *Function = CGF.CGM.CreateRuntimeFunction(
> >>> -        llvm::FunctionType::get(Int8PtrTy, ArgTypes, false),
> >>> "__RTCastToVoid");
> >>> -    llvm::Value *Args[] = {Value};
> >>> -    return CGF.EmitRuntimeCall(Function, Args);
> >>> -  }
> >>> -  // PVOID __RTDynamicCast(
> >>> -  //   PVOID inptr,
> >>> -  //   LONG VfDelta,
> >>> -  //   PVOID SrcType,
> >>> -  //   PVOID TargetType,
> >>> -  //   BOOL isReference)
> >>> -  llvm::Type *ArgTypes[] = {Int8PtrTy, Int32Ty, Int8PtrTy, Int8PtrTy,
> >>> Int32Ty};
> >>> -  llvm::Constant *Function = CGF.CGM.CreateRuntimeFunction(
> >>> -      llvm::FunctionType::get(Int8PtrTy, ArgTypes, false),
> >>> "__RTDynamicCast");
> >>> -  llvm::Value *Args[] = {
> >>> -    Value, Offset,
> >>> -      CGF.CGM.GetAddrOfRTTIDescriptor(SrcTy.getUnqualifiedType()),
> >>> -      CGF.CGM.GetAddrOfRTTIDescriptor(DstTy.getUnqualifiedType()),
> >>> -      llvm::ConstantInt::get(Int32Ty, IsPtrCast ? 0 : 1)};
> >>> -  return CGF.EmitRuntimeCall(Function, Args);
> >>> -}
> >>> -
> >>> -llvm::Value *MSDynamicCastBuilder::emitDynamicCast(llvm::Value
> *Value) {
> >>> -  // Note about undefined behavior: If the dynamic cast is casting to
> a
> >>> -  // reference type and the input is null, we hit a grey area in the
> >>> standard.
> >>> -  // Here we're interpreting the behavior as undefined.  The effects
> are
> >>> the
> >>> -  // following:  If the compiler determines that the argument is
> >>> statically null
> >>> -  // or if the argument is dynamically null but does not require base
> >>> -  // adjustment, __RTDynamicCast will be called with a null argument
> and
> >>> the
> >>> -  // isreference bit set.  In this case __RTDynamicCast will throw
> >>> -  // std::bad_cast. If the argument is dynamically null and a base
> >>> adjustment is
> >>> -  // required the resulting code will produce an out of bounds memory
> >>> reference
> >>> -  // when trying to read VBTblPtr.  In Itanium mode clang also emits a
> >>> vtable
> >>> -  // load that fails at run time.
> >>> -  llvm::PointerType *DstLTy = CGF.ConvertType(DstTy)->getPointerTo();
> >>> -  if (IsCastOfNull && IsPtrCast)
> >>> -    return Builder.CreateBitCast(Value, DstLTy);
> >>> -  if (IsCastOfNull || !IsPtrCast || !SrcDecl)
> >>> -    return Builder.CreateBitCast(emitDynamicCastCall(Value), DstLTy);
> >>> -  // !IsCastOfNull && IsPtrCast && SrcDecl
> >>> -  // In this case we have a pointer that requires a base adjustment.
>  An
> >>> -  // adjustment is only required if the pointer is actually valid so
> >>> here we
> >>> -  // perform a null check before doing the base adjustment and calling
> >>> -  // __RTDynamicCast.  In the case that the argument is null we simply
> >>> return
> >>> -  // null without calling __RTDynamicCast.
> >>> -  llvm::BasicBlock *EntryBlock = Builder.GetInsertBlock();
> >>> -  llvm::BasicBlock *CallBlock =
> >>> CGF.createBasicBlock("dynamic_cast.valid");
> >>> -  llvm::BasicBlock *ExitBlock =
> >>> CGF.createBasicBlock("dynamic_cast.call");
> >>> -  Builder.CreateCondBr(Builder.CreateIsNull(Value), ExitBlock,
> >>> CallBlock);
> >>> -  // Emit the call block and code for it.
> >>> -  CGF.EmitBlock(CallBlock);
> >>> -  Value = emitDynamicCastCall(Value);
> >>> -  // Emit the call block and the phi nodes for it.
> >>> -  CGF.EmitBlock(ExitBlock);
> >>> -  llvm::PHINode *ValuePHI = Builder.CreatePHI(Int8PtrTy, 2);
> >>> -  ValuePHI->addIncoming(Value, CallBlock);
> >>> -  ValuePHI->addIncoming(llvm::Constant::getNullValue(Int8PtrTy),
> >>> EntryBlock);
> >>> -  return Builder.CreateBitCast(ValuePHI, DstLTy);
> >>> -}
> >>> -
> >>>  llvm::Value *CodeGenFunction::EmitDynamicCast(llvm::Value *Value,
> >>>                                                const CXXDynamicCastExpr
> >>> *DCE) {
> >>> -  if (getTarget().getCXXABI().isMicrosoft()) {
> >>> -    MSDynamicCastBuilder Builder(*this, DCE);
> >>> -    return Builder.emitDynamicCast(Value);
> >>> -  }
> >>> -
> >>>    QualType DestTy = DCE->getTypeAsWritten();
> >>>
> >>>    if (DCE->isAlwaysNull())
> >>> -    return EmitDynamicCastToNull(*this, DestTy);
> >>> +    if (llvm::Value *T = EmitDynamicCastToNull(*this, DestTy))
> >>> +      return T;
> >>>
> >>>    QualType SrcTy = DCE->getSubExpr()->getType();
> >>>
> >>> +  // C++ [expr.dynamic.cast]p7:
> >>> +  //   If T is "pointer to cv void," then the result is a pointer to
> the
> >>> most
> >>> +  //   derived object pointed to by v.
> >>> +  const PointerType *DestPTy = DestTy->getAs<PointerType>();
> >>> +
> >>> +  bool isDynamicCastToVoid;
> >>> +  QualType SrcRecordTy;
> >>> +  QualType DestRecordTy;
> >>> +  if (DestPTy) {
> >>> +    isDynamicCastToVoid = DestPTy->getPointeeType()->isVoidType();
> >>> +    SrcRecordTy = SrcTy->castAs<PointerType>()->getPointeeType();
> >>> +    DestRecordTy = DestPTy->getPointeeType();
> >>> +  } else {
> >>> +    isDynamicCastToVoid = false;
> >>> +    SrcRecordTy = SrcTy;
> >>> +    DestRecordTy = DestTy->castAs<ReferenceType>()->getPointeeType();
> >>> +  }
> >>> +
> >>> +  assert(SrcRecordTy->isRecordType() && "source type must be a record
> >>> type!");
> >>> +
> >>>    // C++ [expr.dynamic.cast]p4:
> >>>    //   If the value of v is a null pointer value in the pointer case,
> >>> the result
> >>>    //   is the null pointer value of type T.
> >>> -  bool ShouldNullCheckSrcValue = SrcTy->isPointerType();
> >>> +  bool ShouldNullCheckSrcValue =
> >>> +
> >>>
> CGM.getCXXABI().shouldDynamicCastCallBeNullChecked(SrcTy->isPointerType(),
> >>> +                                                         SrcRecordTy);
> >>>
> >>>    llvm::BasicBlock *CastNull = nullptr;
> >>>    llvm::BasicBlock *CastNotNull = nullptr;
> >>> @@ -2058,7 +1736,15 @@ llvm::Value *CodeGenFunction::EmitDynami
> >>>      EmitBlock(CastNotNull);
> >>>    }
> >>>
> >>> -  Value = EmitItaniumDynamicCastCall(*this, Value, SrcTy, DestTy,
> >>> CastEnd);
> >>> +  if (isDynamicCastToVoid) {
> >>> +    Value = CGM.getCXXABI().EmitDynamicCastToVoid(*this, Value,
> >>> SrcRecordTy,
> >>> +                                                  DestTy);
> >>> +  } else {
> >>> +    assert(DestRecordTy->isRecordType() &&
> >>> +           "destination type must be a record type!");
> >>> +    Value = CGM.getCXXABI().EmitDynamicCastCall(*this, Value,
> >>> SrcRecordTy,
> >>> +                                                DestTy, DestRecordTy,
> >>> CastEnd);
> >>> +  }
> >>>
> >>>    if (ShouldNullCheckSrcValue) {
> >>>      EmitBranch(CastEnd);
> >>>
> >>> Modified: cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp
> >>> URL:
> >>>
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp?rev=211473&r1=211472&r2=211473&view=diff
> >>>
> >>>
> ==============================================================================
> >>> --- cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp (original)
> >>> +++ cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp Sun Jun 22 14:05:33 2014
> >>> @@ -25,6 +25,7 @@
> >>>  #include "CodeGenModule.h"
> >>>  #include "clang/AST/Mangle.h"
> >>>  #include "clang/AST/Type.h"
> >>> +#include "llvm/IR/CallSite.h"
> >>>  #include "llvm/IR/DataLayout.h"
> >>>  #include "llvm/IR/Intrinsics.h"
> >>>  #include "llvm/IR/Value.h"
> >>> @@ -108,6 +109,26 @@ public:
> >>>    llvm::Value *adjustToCompleteObject(CodeGenFunction &CGF,
> llvm::Value
> >>> *ptr,
> >>>                                        QualType type) override;
> >>>
> >>> +  bool shouldTypeidBeNullChecked(bool IsDeref, QualType SrcRecordTy)
> >>> override;
> >>> +  void EmitBadTypeidCall(CodeGenFunction &CGF) override;
> >>> +  llvm::Value *EmitTypeid(CodeGenFunction &CGF, QualType SrcRecordTy,
> >>> +                          llvm::Value *ThisPtr,
> >>> +                          llvm::Type *StdTypeInfoPtrTy) override;
> >>> +
> >>> +  bool shouldDynamicCastCallBeNullChecked(bool SrcIsPtr,
> >>> +                                          QualType SrcRecordTy)
> >>> override;
> >>> +
> >>> +  llvm::Value *EmitDynamicCastCall(CodeGenFunction &CGF, llvm::Value
> >>> *Value,
> >>> +                                   QualType SrcRecordTy, QualType
> >>> DestTy,
> >>> +                                   QualType DestRecordTy,
> >>> +                                   llvm::BasicBlock *CastEnd)
> override;
> >>> +
> >>> +  llvm::Value *EmitDynamicCastToVoid(CodeGenFunction &CGF, llvm::Value
> >>> *Value,
> >>> +                                     QualType SrcRecordTy,
> >>> +                                     QualType DestTy) override;
> >>> +
> >>> +  bool EmitBadCastCall(CodeGenFunction &CGF) override;
> >>> +
> >>>    llvm::Value *
> >>>      GetVirtualBaseClassOffset(CodeGenFunction &CGF, llvm::Value *This,
> >>>                                const CXXRecordDecl *ClassDecl,
> >>> @@ -800,6 +821,194 @@ llvm::Value *ItaniumCXXABI::adjustToComp
> >>>    return CGF.Builder.CreateInBoundsGEP(ptr, offset);
> >>>  }
> >>>
> >>> +static llvm::Constant *getItaniumDynamicCastFn(CodeGenFunction &CGF) {
> >>> +  // void *__dynamic_cast(const void *sub,
> >>> +  //                      const abi::__class_type_info *src,
> >>> +  //                      const abi::__class_type_info *dst,
> >>> +  //                      std::ptrdiff_t src2dst_offset);
> >>> +
> >>> +  llvm::Type *Int8PtrTy = CGF.Int8PtrTy;
> >>> +  llvm::Type *PtrDiffTy =
> >>> +    CGF.ConvertType(CGF.getContext().getPointerDiffType());
> >>> +
> >>> +  llvm::Type *Args[4] = { Int8PtrTy, Int8PtrTy, Int8PtrTy, PtrDiffTy
> };
> >>> +
> >>> +  llvm::FunctionType *FTy = llvm::FunctionType::get(Int8PtrTy, Args,
> >>> false);
> >>> +
> >>> +  // Mark the function as nounwind readonly.
> >>> +  llvm::Attribute::AttrKind FuncAttrs[] = { llvm::Attribute::NoUnwind,
> >>> +                                            llvm::Attribute::ReadOnly
> };
> >>> +  llvm::AttributeSet Attrs = llvm::AttributeSet::get(
> >>> +      CGF.getLLVMContext(), llvm::AttributeSet::FunctionIndex,
> >>> FuncAttrs);
> >>> +
> >>> +  return CGF.CGM.CreateRuntimeFunction(FTy, "__dynamic_cast", Attrs);
> >>> +}
> >>> +
> >>> +static llvm::Constant *getBadCastFn(CodeGenFunction &CGF) {
> >>> +  // void __cxa_bad_cast();
> >>> +  llvm::FunctionType *FTy = llvm::FunctionType::get(CGF.VoidTy,
> false);
> >>> +  return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_bad_cast");
> >>> +}
> >>> +
> >>> +/// \brief Compute the src2dst_offset hint as described in the
> >>> +/// Itanium C++ ABI [2.9.7]
> >>> +static CharUnits computeOffsetHint(ASTContext &Context,
> >>> +                                   const CXXRecordDecl *Src,
> >>> +                                   const CXXRecordDecl *Dst) {
> >>> +  CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
> >>> +                     /*DetectVirtual=*/false);
> >>> +
> >>> +  // If Dst is not derived from Src we can skip the whole computation
> >>> below and
> >>> +  // return that Src is not a public base of Dst.  Record all
> >>> inheritance paths.
> >>> +  if (!Dst->isDerivedFrom(Src, Paths))
> >>> +    return CharUnits::fromQuantity(-2ULL);
> >>> +
> >>> +  unsigned NumPublicPaths = 0;
> >>> +  CharUnits Offset;
> >>> +
> >>> +  // Now walk all possible inheritance paths.
> >>> +  for (CXXBasePaths::paths_iterator I = Paths.begin(), E =
> Paths.end();
> >>> I != E;
> >>> +       ++I) {
> >>> +    if (I->Access != AS_public) // Ignore non-public inheritance.
> >>> +      continue;
> >>> +
> >>> +    ++NumPublicPaths;
> >>> +
> >>> +    for (CXXBasePath::iterator J = I->begin(), JE = I->end(); J != JE;
> >>> ++J) {
> >>> +      // If the path contains a virtual base class we can't give any
> >>> hint.
> >>> +      // -1: no hint.
> >>> +      if (J->Base->isVirtual())
> >>> +        return CharUnits::fromQuantity(-1ULL);
> >>> +
> >>> +      if (NumPublicPaths > 1) // Won't use offsets, skip computation.
> >>> +        continue;
> >>> +
> >>> +      // Accumulate the base class offsets.
> >>> +      const ASTRecordLayout &L = Context.getASTRecordLayout(J->Class);
> >>> +      Offset +=
> >>> L.getBaseClassOffset(J->Base->getType()->getAsCXXRecordDecl());
> >>> +    }
> >>> +  }
> >>> +
> >>> +  // -2: Src is not a public base of Dst.
> >>> +  if (NumPublicPaths == 0)
> >>> +    return CharUnits::fromQuantity(-2ULL);
> >>> +
> >>> +  // -3: Src is a multiple public base type but never a virtual base
> >>> type.
> >>> +  if (NumPublicPaths > 1)
> >>> +    return CharUnits::fromQuantity(-3ULL);
> >>> +
> >>> +  // Otherwise, the Src type is a unique public nonvirtual base type
> of
> >>> Dst.
> >>> +  // Return the offset of Src from the origin of Dst.
> >>> +  return Offset;
> >>> +}
> >>> +
> >>> +static llvm::Constant *getBadTypeidFn(CodeGenFunction &CGF) {
> >>> +  // void __cxa_bad_typeid();
> >>> +  llvm::FunctionType *FTy = llvm::FunctionType::get(CGF.VoidTy,
> false);
> >>> +
> >>> +  return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_bad_typeid");
> >>> +}
> >>> +
> >>> +bool ItaniumCXXABI::shouldTypeidBeNullChecked(bool IsDeref,
> >>> +                                              QualType SrcRecordTy) {
> >>> +  return IsDeref;
> >>> +}
> >>> +
> >>> +void ItaniumCXXABI::EmitBadTypeidCall(CodeGenFunction &CGF) {
> >>> +  llvm::Value *Fn = getBadTypeidFn(CGF);
> >>> +  CGF.EmitRuntimeCallOrInvoke(Fn).setDoesNotReturn();
> >>> +  CGF.Builder.CreateUnreachable();
> >>> +}
> >>> +
> >>> +llvm::Value *ItaniumCXXABI::EmitTypeid(CodeGenFunction &CGF,
> >>> +                                       QualType SrcRecordTy,
> >>> +                                       llvm::Value *ThisPtr,
> >>> +                                       llvm::Type *StdTypeInfoPtrTy) {
> >>> +  llvm::Value *Value =
> >>> +      CGF.GetVTablePtr(ThisPtr, StdTypeInfoPtrTy->getPointerTo());
> >>> +
> >>> +  // Load the type info.
> >>> +  Value = CGF.Builder.CreateConstInBoundsGEP1_64(Value, -1ULL);
> >>> +  return CGF.Builder.CreateLoad(Value);
> >>> +}
> >>> +
> >>> +bool ItaniumCXXABI::shouldDynamicCastCallBeNullChecked(bool SrcIsPtr,
> >>> +                                                       QualType
> >>> SrcRecordTy) {
> >>> +  return SrcIsPtr;
> >>> +}
> >>> +
> >>> +llvm::Value *ItaniumCXXABI::EmitDynamicCastCall(
> >>> +    CodeGenFunction &CGF, llvm::Value *Value, QualType SrcRecordTy,
> >>> +    QualType DestTy, QualType DestRecordTy, llvm::BasicBlock
> *CastEnd) {
> >>> +  llvm::Type *PtrDiffLTy =
> >>> +      CGF.ConvertType(CGF.getContext().getPointerDiffType());
> >>> +  llvm::Type *DestLTy = CGF.ConvertType(DestTy);
> >>> +
> >>> +  llvm::Value *SrcRTTI =
> >>> +
>  CGF.CGM.GetAddrOfRTTIDescriptor(SrcRecordTy.getUnqualifiedType());
> >>> +  llvm::Value *DestRTTI =
> >>> +
> >>> CGF.CGM.GetAddrOfRTTIDescriptor(DestRecordTy.getUnqualifiedType());
> >>> +
> >>> +  // Compute the offset hint.
> >>> +  const CXXRecordDecl *SrcDecl = SrcRecordTy->getAsCXXRecordDecl();
> >>> +  const CXXRecordDecl *DestDecl = DestRecordTy->getAsCXXRecordDecl();
> >>> +  llvm::Value *OffsetHint = llvm::ConstantInt::get(
> >>> +      PtrDiffLTy,
> >>> +      computeOffsetHint(CGF.getContext(), SrcDecl,
> >>> DestDecl).getQuantity());
> >>> +
> >>> +  // Emit the call to __dynamic_cast.
> >>> +  Value = CGF.EmitCastToVoidPtr(Value);
> >>> +
> >>> +  llvm::Value *args[] = {Value, SrcRTTI, DestRTTI, OffsetHint};
> >>> +  Value = CGF.EmitNounwindRuntimeCall(getItaniumDynamicCastFn(CGF),
> >>> args);
> >>> +  Value = CGF.Builder.CreateBitCast(Value, DestLTy);
> >>> +
> >>> +  /// C++ [expr.dynamic.cast]p9:
> >>> +  ///   A failed cast to reference type throws std::bad_cast
> >>> +  if (DestTy->isReferenceType()) {
> >>> +    llvm::BasicBlock *BadCastBlock =
> >>> +        CGF.createBasicBlock("dynamic_cast.bad_cast");
> >>> +
> >>> +    llvm::Value *IsNull = CGF.Builder.CreateIsNull(Value);
> >>> +    CGF.Builder.CreateCondBr(IsNull, BadCastBlock, CastEnd);
> >>> +
> >>> +    CGF.EmitBlock(BadCastBlock);
> >>> +    EmitBadCastCall(CGF);
> >>> +  }
> >>> +
> >>> +  return Value;
> >>> +}
> >>> +
> >>> +llvm::Value *ItaniumCXXABI::EmitDynamicCastToVoid(CodeGenFunction
> &CGF,
> >>> +                                                  llvm::Value *Value,
> >>> +                                                  QualType
> SrcRecordTy,
> >>> +                                                  QualType DestTy) {
> >>> +  llvm::Type *PtrDiffLTy =
> >>> +      CGF.ConvertType(CGF.getContext().getPointerDiffType());
> >>> +  llvm::Type *DestLTy = CGF.ConvertType(DestTy);
> >>> +
> >>> +  // Get the vtable pointer.
> >>> +  llvm::Value *VTable = CGF.GetVTablePtr(Value,
> >>> PtrDiffLTy->getPointerTo());
> >>> +
> >>> +  // Get the offset-to-top from the vtable.
> >>> +  llvm::Value *OffsetToTop =
> >>> +      CGF.Builder.CreateConstInBoundsGEP1_64(VTable, -2ULL);
> >>> +  OffsetToTop = CGF.Builder.CreateLoad(OffsetToTop, "offset.to.top");
> >>> +
> >>> +  // Finally, add the offset to the pointer.
> >>> +  Value = CGF.EmitCastToVoidPtr(Value);
> >>> +  Value = CGF.Builder.CreateInBoundsGEP(Value, OffsetToTop);
> >>> +
> >>> +  return CGF.Builder.CreateBitCast(Value, DestLTy);
> >>> +}
> >>> +
> >>> +bool ItaniumCXXABI::EmitBadCastCall(CodeGenFunction &CGF) {
> >>> +  llvm::Value *Fn = getBadCastFn(CGF);
> >>> +  CGF.EmitRuntimeCallOrInvoke(Fn).setDoesNotReturn();
> >>> +  CGF.Builder.CreateUnreachable();
> >>> +  return true;
> >>> +}
> >>> +
> >>>  llvm::Value *
> >>>  ItaniumCXXABI::GetVirtualBaseClassOffset(CodeGenFunction &CGF,
> >>>                                           llvm::Value *This,
> >>>
> >>> Modified: cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp
> >>> URL:
> >>>
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp?rev=211473&r1=211472&r2=211473&view=diff
> >>>
> >>>
> ==============================================================================
> >>> --- cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp (original)
> >>> +++ cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp Sun Jun 22 14:05:33 2014
> >>> @@ -21,6 +21,7 @@
> >>>  #include "clang/AST/DeclCXX.h"
> >>>  #include "clang/AST/VTableBuilder.h"
> >>>  #include "llvm/ADT/StringSet.h"
> >>> +#include "llvm/IR/CallSite.h"
> >>>
> >>>  using namespace clang;
> >>>  using namespace CodeGen;
> >>> @@ -56,6 +57,26 @@ public:
> >>>                                        llvm::Value *ptr,
> >>>                                        QualType type) override;
> >>>
> >>> +  bool shouldTypeidBeNullChecked(bool IsDeref, QualType SrcRecordTy)
> >>> override;
> >>> +  void EmitBadTypeidCall(CodeGenFunction &CGF) override;
> >>> +  llvm::Value *EmitTypeid(CodeGenFunction &CGF, QualType SrcRecordTy,
> >>> +                          llvm::Value *ThisPtr,
> >>> +                          llvm::Type *StdTypeInfoPtrTy) override;
> >>> +
> >>> +  bool shouldDynamicCastCallBeNullChecked(bool SrcIsPtr,
> >>> +                                          QualType SrcRecordTy)
> >>> override;
> >>> +
> >>> +  llvm::Value *EmitDynamicCastCall(CodeGenFunction &CGF, llvm::Value
> >>> *Value,
> >>> +                                   QualType SrcRecordTy, QualType
> >>> DestTy,
> >>> +                                   QualType DestRecordTy,
> >>> +                                   llvm::BasicBlock *CastEnd)
> override;
> >>> +
> >>> +  llvm::Value *EmitDynamicCastToVoid(CodeGenFunction &CGF, llvm::Value
> >>> *Value,
> >>> +                                     QualType SrcRecordTy,
> >>> +                                     QualType DestTy) override;
> >>> +
> >>> +  bool EmitBadCastCall(CodeGenFunction &CGF) override;
> >>> +
> >>>    llvm::Value *
> >>>    GetVirtualBaseClassOffset(CodeGenFunction &CGF, llvm::Value *This,
> >>>                              const CXXRecordDecl *ClassDecl,
> >>> @@ -469,6 +490,129 @@ llvm::Value *MicrosoftCXXABI::adjustToCo
> >>>    return ptr;
> >>>  }
> >>>
> >>> +/// \brief Gets the offset to the virtual base that contains the vfptr
> >>> for
> >>> +/// MS-ABI polymorphic types.
> >>> +static llvm::Value *getPolymorphicOffset(CodeGenFunction &CGF,
> >>> +                                         const CXXRecordDecl *RD,
> >>> +                                         llvm::Value *Value) {
> >>> +  const ASTContext &Context = RD->getASTContext();
> >>> +  for (const CXXBaseSpecifier &Base : RD->vbases())
> >>> +    if
> (Context.getASTRecordLayout(Base.getType()->getAsCXXRecordDecl())
> >>> +            .hasExtendableVFPtr())
> >>> +      return CGF.CGM.getCXXABI().GetVirtualBaseClassOffset(
> >>> +          CGF, Value, RD, Base.getType()->getAsCXXRecordDecl());
> >>> +  llvm_unreachable("One of our vbases should be polymorphic.");
> >>> +}
> >>> +
> >>> +static std::pair<llvm::Value *, llvm::Value *>
> >>> +performBaseAdjustment(CodeGenFunction &CGF, llvm::Value *Value,
> >>> +                      QualType SrcRecordTy) {
> >>> +  Value = CGF.Builder.CreateBitCast(Value, CGF.Int8PtrTy);
> >>> +  const CXXRecordDecl *SrcDecl = SrcRecordTy->getAsCXXRecordDecl();
> >>> +
> >>> +  if
> (CGF.getContext().getASTRecordLayout(SrcDecl).hasExtendableVFPtr())
> >>> +    return std::make_pair(Value, llvm::ConstantInt::get(CGF.Int32Ty,
> >>> 0));
> >>> +
> >>> +  // Perform a base adjustment.
> >>> +  llvm::Value *Offset = getPolymorphicOffset(CGF, SrcDecl, Value);
> >>> +  Value = CGF.Builder.CreateInBoundsGEP(Value, Offset);
> >>> +  Offset = CGF.Builder.CreateTrunc(Offset, CGF.Int32Ty);
> >>> +  return std::make_pair(Value, Offset);
> >>> +}
> >>> +
> >>> +bool MicrosoftCXXABI::shouldTypeidBeNullChecked(bool IsDeref,
> >>> +                                                QualType SrcRecordTy)
> {
> >>> +  const CXXRecordDecl *SrcDecl = SrcRecordTy->getAsCXXRecordDecl();
> >>> +  return IsDeref &&
> >>> +
> >>> !CGM.getContext().getASTRecordLayout(SrcDecl).hasExtendableVFPtr();
> >>> +}
> >>> +
> >>> +static llvm::CallSite emitRTtypeidCall(CodeGenFunction &CGF,
> >>> +                                       llvm::Value *Argument) {
> >>> +  llvm::Type *ArgTypes[] = {CGF.Int8PtrTy};
> >>> +  llvm::FunctionType *FTy =
> >>> +      llvm::FunctionType::get(CGF.Int8PtrTy, ArgTypes, false);
> >>> +  llvm::Value *Args[] = {Argument};
> >>> +  llvm::Constant *Fn = CGF.CGM.CreateRuntimeFunction(FTy,
> "__RTtypeid");
> >>> +  return CGF.EmitRuntimeCallOrInvoke(Fn, Args);
> >>> +}
> >>> +
> >>> +void MicrosoftCXXABI::EmitBadTypeidCall(CodeGenFunction &CGF) {
> >>> +  llvm::CallSite Call =
> >>> +      emitRTtypeidCall(CGF,
> >>> llvm::Constant::getNullValue(CGM.VoidPtrTy));
> >>> +  Call.setDoesNotReturn();
> >>> +  CGF.Builder.CreateUnreachable();
> >>> +}
> >>> +
> >>> +llvm::Value *MicrosoftCXXABI::EmitTypeid(CodeGenFunction &CGF,
> >>> +                                         QualType SrcRecordTy,
> >>> +                                         llvm::Value *ThisPtr,
> >>> +                                         llvm::Type
> *StdTypeInfoPtrTy) {
> >>> +  llvm::Value *Offset;
> >>> +  std::tie(ThisPtr, Offset) = performBaseAdjustment(CGF, ThisPtr,
> >>> SrcRecordTy);
> >>> +  return CGF.Builder.CreateBitCast(
> >>> +      emitRTtypeidCall(CGF, ThisPtr).getInstruction(),
> >>> StdTypeInfoPtrTy);
> >>> +}
> >>> +
> >>> +bool MicrosoftCXXABI::shouldDynamicCastCallBeNullChecked(bool
> SrcIsPtr,
> >>> +                                                         QualType
> >>> SrcRecordTy) {
> >>> +  const CXXRecordDecl *SrcDecl = SrcRecordTy->getAsCXXRecordDecl();
> >>> +  return SrcIsPtr &&
> >>> +
> >>> !CGM.getContext().getASTRecordLayout(SrcDecl).hasExtendableVFPtr();
> >>> +}
> >>> +
> >>> +llvm::Value *MicrosoftCXXABI::EmitDynamicCastCall(
> >>> +    CodeGenFunction &CGF, llvm::Value *Value, QualType SrcRecordTy,
> >>> +    QualType DestTy, QualType DestRecordTy, llvm::BasicBlock
> *CastEnd) {
> >>> +  llvm::Type *DestLTy = CGF.ConvertType(DestTy);
> >>> +
> >>> +  llvm::Value *SrcRTTI =
> >>> +
>  CGF.CGM.GetAddrOfRTTIDescriptor(SrcRecordTy.getUnqualifiedType());
> >>> +  llvm::Value *DestRTTI =
> >>> +
> >>> CGF.CGM.GetAddrOfRTTIDescriptor(DestRecordTy.getUnqualifiedType());
> >>> +
> >>> +  llvm::Value *Offset;
> >>> +  std::tie(Value, Offset) = performBaseAdjustment(CGF, Value,
> >>> SrcRecordTy);
> >>> +
> >>> +  // PVOID __RTDynamicCast(
> >>> +  //   PVOID inptr,
> >>> +  //   LONG VfDelta,
> >>> +  //   PVOID SrcType,
> >>> +  //   PVOID TargetType,
> >>> +  //   BOOL isReference)
> >>> +  llvm::Type *ArgTypes[] = {CGF.Int8PtrTy, CGF.Int32Ty, CGF.Int8PtrTy,
> >>> +                            CGF.Int8PtrTy, CGF.Int32Ty};
> >>> +  llvm::Constant *Function = CGF.CGM.CreateRuntimeFunction(
> >>> +      llvm::FunctionType::get(CGF.Int8PtrTy, ArgTypes, false),
> >>> +      "__RTDynamicCast");
> >>> +  llvm::Value *Args[] = {
> >>> +      Value, Offset, SrcRTTI, DestRTTI,
> >>> +      llvm::ConstantInt::get(CGF.Int32Ty, DestTy->isReferenceType())};
> >>> +  Value = CGF.EmitRuntimeCallOrInvoke(Function,
> Args).getInstruction();
> >>> +  return CGF.Builder.CreateBitCast(Value, DestLTy);
> >>> +}
> >>> +
> >>> +llvm::Value *
> >>> +MicrosoftCXXABI::EmitDynamicCastToVoid(CodeGenFunction &CGF,
> llvm::Value
> >>> *Value,
> >>> +                                       QualType SrcRecordTy,
> >>> +                                       QualType DestTy) {
> >>> +  llvm::Value *Offset;
> >>> +  std::tie(Value, Offset) = performBaseAdjustment(CGF, Value,
> >>> SrcRecordTy);
> >>> +
> >>> +  // PVOID __RTCastToVoid(
> >>> +  //   PVOID inptr)
> >>> +  llvm::Type *ArgTypes[] = {CGF.Int8PtrTy};
> >>> +  llvm::Constant *Function = CGF.CGM.CreateRuntimeFunction(
> >>> +      llvm::FunctionType::get(CGF.Int8PtrTy, ArgTypes, false),
> >>> +      "__RTCastToVoid");
> >>> +  llvm::Value *Args[] = {Value};
> >>> +  return CGF.EmitRuntimeCall(Function, Args);
> >>> +}
> >>> +
> >>> +bool MicrosoftCXXABI::EmitBadCastCall(CodeGenFunction &CGF) {
> >>> +  return false;
> >>> +}
> >>> +
> >>>  llvm::Value *
> >>>  MicrosoftCXXABI::GetVirtualBaseClassOffset(CodeGenFunction &CGF,
> >>>                                             llvm::Value *This,
> >>>
> >>> Modified: cfe/trunk/test/CodeGenCXX/microsoft-abi-dynamic-cast.cpp
> >>> URL:
> >>>
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/microsoft-abi-dynamic-cast.cpp?rev=211473&r1=211472&r2=211473&view=diff
> >>>
> >>>
> ==============================================================================
> >>> --- cfe/trunk/test/CodeGenCXX/microsoft-abi-dynamic-cast.cpp (original)
> >>> +++ cfe/trunk/test/CodeGenCXX/microsoft-abi-dynamic-cast.cpp Sun Jun 22
> >>> 14:05:33 2014
> >>> @@ -1,158 +1,130 @@
> >>> -// RUN: %clang_cc1 -emit-llvm -O2 -optzns -o - -triple=i386-pc-win32
> >>> 2>/dev/null %s | FileCheck %s
> >>> -// REQUIRES: asserts
> >>> +// RUN: %clang_cc1 -emit-llvm -O1 -o - -triple=i386-pc-win32 %s |
> >>> FileCheck %s
> >>>
> >>>  struct S { char a; };
> >>> -struct V { virtual void f(){} };
> >>> +struct V { virtual void f(); };
> >>>  struct A : virtual V {};
> >>>  struct B : S, virtual V {};
> >>>  struct T {};
> >>>
> >>>  T* test0() { return dynamic_cast<T*>((B*)0); }
> >>> -// CHECK: define noalias %struct.T* @"\01?test0@@YAPAUT@@XZ"() #0 {
> >>> -// CHECK-NEXT: entry:
> >>> -// CHECK-NEXT:   ret %struct.T* null
> >>> -// CHECK-NEXT: }
> >>> +// CHECK-LABEL: define noalias %struct.T* @"\01?test0@@YAPAUT@@XZ"()
> >>> +// CHECK:   ret %struct.T* null
> >>>
> >>>  T* test1(V* x) { return &dynamic_cast<T&>(*x); }
> >>> -// CHECK: define %struct.T* @"\01?test1@@YAPAUT@@PAUV@@@Z"(%struct.V*
> >>> %x) #1 {
> >>> -// CHECK-NEXT: entry:
> >>> -// CHECK-NEXT:   %0 = bitcast %struct.V* %x to i8*
> >>> -// CHECK-NEXT:   %1 = tail call i8* @__RTDynamicCast(i8* %0, i32 0,
> i8*
> >>> bitcast (%"MSRTTITypeDescriptor\07"* @"\01??_R0?AUV@@@8" to i8*), i8*
> >>> bitcast (%"MSRTTITypeDescriptor\07"* @"\01??_R0?AUT@@@8" to i8*), i32
> 1) #2
> >>> -// CHECK-NEXT:   %2 = bitcast i8* %1 to %struct.T*
> >>> -// CHECK-NEXT:   ret %struct.T* %2
> >>> -// CHECK-NEXT: }
> >>> +// CHECK-LABEL: define %struct.T*
> >>> @"\01?test1@@YAPAUT@@PAUV@@@Z"(%struct.V* %x)
> >>> +// CHECK:        [[CAST:%.*]] = bitcast %struct.V* %x to i8*
> >>> +// CHECK-NEXT:   [[CALL:%.*]] = tail call i8* @__RTDynamicCast(i8*
> >>> [[CAST]], i32 0, i8* bitcast (%"MSRTTITypeDescriptor\07"*
> >>> @"\01??_R0?AUV@@@8" to i8*), i8* bitcast (%"MSRTTITypeDescriptor\07"*
> >>> @"\01??_R0?AUT@@@8" to i8*), i32 1)
> >>> +// CHECK-NEXT:   [[RET:%.*]] = bitcast i8* [[CALL]] to %struct.T*
> >>> +// CHECK-NEXT:   ret %struct.T* [[RET]]
> >>>
> >>>  T* test2(A* x) { return &dynamic_cast<T&>(*x); }
> >>> -// CHECK: define %struct.T* @"\01?test2@@YAPAUT@@PAUA@@@Z"(%struct.A*
> >>> %x) #1 {
> >>> -// CHECK-NEXT: entry:
> >>> -// CHECK-NEXT:   %0 = bitcast %struct.A* %x to i8*
> >>> -// CHECK-NEXT:   %1 = bitcast %struct.A* %x to i8**
> >>> -// CHECK-NEXT:   %vbtable = load i8** %1, align 4
> >>> -// CHECK-NEXT:   %2 = getelementptr inbounds i8* %vbtable, i32 4
> >>> -// CHECK-NEXT:   %3 = bitcast i8* %2 to i32*
> >>> -// CHECK-NEXT:   %vbase_offs = load i32* %3, align 4
> >>> -// CHECK-NEXT:   %4 = getelementptr inbounds i8* %0, i32 %vbase_offs
> >>> -// CHECK-NEXT:   %5 = tail call i8* @__RTDynamicCast(i8* %4, i32
> >>> %vbase_offs, i8* bitcast (%"MSRTTITypeDescriptor\07"* @"\01??_R0?AUA@@@8"
> to
> >>> i8*), i8* bitcast (%"MSRTTITypeDescriptor\07"* @"\01??_R0?AUT@@@8" to
> i8*),
> >>> i32 1) #2
> >>> -// CHECK-NEXT:   %6 = bitcast i8* %5 to %struct.T*
> >>> -// CHECK-NEXT:   ret %struct.T* %6
> >>> -// CHECK-NEXT: }
> >>> +// CHECK-LABEL: define %struct.T*
> >>> @"\01?test2@@YAPAUT@@PAUA@@@Z"(%struct.A* %x)
> >>> +// CHECK:        [[CAST:%.*]] = bitcast %struct.A* %x to i8*
> >>> +// CHECK-NEXT:   [[BITCAST:%.*]] = bitcast %struct.A* %x to i8**
> >>> +// CHECK-NEXT:   [[VBTBL:%.*]] = load i8** [[BITCAST]], align 4
> >>> +// CHECK-NEXT:   [[VBOFFP:%.*]] = getelementptr inbounds i8*
> [[VBTBL]],
> >>> i32 4
> >>> +// CHECK-NEXT:   [[VBOFFPCAST:%.*]] = bitcast i8* [[VBOFFP]] to i32*
> >>> +// CHECK-NEXT:   [[VBOFFS:%.*]] = load i32* [[VBOFFPCAST]], align 4
> >>> +// CHECK-NEXT:   [[ADJ:%.*]] = getelementptr inbounds i8* [[CAST]],
> i32
> >>> [[VBOFFS]]
> >>> +// CHECK-NEXT:   [[CALL:%.*]] = tail call i8* @__RTDynamicCast(i8*
> >>> [[ADJ]], i32 [[VBOFFS]], i8* bitcast (%"MSRTTITypeDescriptor\07"*
> >>> @"\01??_R0?AUA@@@8" to i8*), i8* bitcast (%"MSRTTITypeDescriptor\07"*
> >>> @"\01??_R0?AUT@@@8" to i8*), i32 1)
> >>> +// CHECK-NEXT:   [[RET:%.*]] = bitcast i8* [[CALL]] to %struct.T*
> >>> +// CHECK-NEXT:   ret %struct.T* [[RET]]
> >>>
> >>>  T* test3(B* x) { return &dynamic_cast<T&>(*x); }
> >>> -// CHECK: define %struct.T* @"\01?test3@@YAPAUT@@PAUB@@@Z"(%struct.B*
> >>> %x) #1 {
> >>> -// CHECK-NEXT: entry:
> >>> -// CHECK-NEXT:   %0 = getelementptr inbounds %struct.B* %x, i32 0, i32
> >>> 0, i32 0
> >>> -// CHECK-NEXT:   %vbptr = getelementptr inbounds i8* %0, i32 4
> >>> -// CHECK-NEXT:   %1 = bitcast i8* %vbptr to i8**
> >>> -// CHECK-NEXT:   %vbtable = load i8** %1, align 4
> >>> -// CHECK-NEXT:   %2 = getelementptr inbounds i8* %vbtable, i32 4
> >>> -// CHECK-NEXT:   %3 = bitcast i8* %2 to i32*
> >>> -// CHECK-NEXT:   %vbase_offs = load i32* %3, align 4
> >>> -// CHECK-NEXT:   %4 = add nsw i32 %vbase_offs, 4
> >>> -// CHECK-NEXT:   %5 = getelementptr inbounds i8* %0, i32 %4
> >>> -// CHECK-NEXT:   %6 = tail call i8* @__RTDynamicCast(i8* %5, i32 %4,
> i8*
> >>> bitcast (%"MSRTTITypeDescriptor\07"* @"\01??_R0?AUB@@@8" to i8*), i8*
> >>> bitcast (%"MSRTTITypeDescriptor\07"* @"\01??_R0?AUT@@@8" to i8*), i32
> 1) #2
> >>> -// CHECK-NEXT:   %7 = bitcast i8* %6 to %struct.T*
> >>> -// CHECK-NEXT:   ret %struct.T* %7
> >>> -// CHECK-NEXT: }
> >>> +// CHECK-LABEL: define %struct.T*
> >>> @"\01?test3@@YAPAUT@@PAUB@@@Z"(%struct.B* %x)
> >>> +// CHECK:        [[VOIDP:%.*]] = getelementptr inbounds %struct.B* %x,
> >>> i32 0, i32 0, i32 0
> >>> +// CHECK-NEXT:   [[VBPTR:%.*]] = getelementptr inbounds i8* [[VOIDP]],
> >>> i32 4
> >>> +// CHECK-NEXT:   [[BITCAST:%.*]] = bitcast i8* [[VBPTR:%.*]] to i8**
> >>> +// CHECK-NEXT:   [[VBTBL:%.*]] = load i8** [[BITCAST]], align 4
> >>> +// CHECK-NEXT:   [[VBOFFP:%.*]] = getelementptr inbounds i8*
> [[VBTBL]],
> >>> i32 4
> >>> +// CHECK-NEXT:   [[VBOFFPCAST:%.*]] = bitcast i8* [[VBOFFP]] to i32*
> >>> +// CHECK-NEXT:   [[VBOFFS:%.*]] = load i32* [[VBOFFPCAST]], align 4
> >>> +// CHECK-NEXT:   [[DELTA:%.*]] = add nsw i32 [[VBOFFS]], 4
> >>> +// CHECK-NEXT:   [[ADJ:%.*]] = getelementptr inbounds i8* [[VOIDP]],
> i32
> >>> [[DELTA]]
> >>> +// CHECK-NEXT:   [[CALL:%.*]] = tail call i8* @__RTDynamicCast(i8*
> >>> [[ADJ]], i32 [[DELTA]], i8* bitcast (%"MSRTTITypeDescriptor\07"*
> >>> @"\01??_R0?AUB@@@8" to i8*), i8* bitcast (%"MSRTTITypeDescriptor\07"*
> >>> @"\01??_R0?AUT@@@8" to i8*), i32 1)
> >>> +// CHECK-NEXT:   [[RET:%.*]] = bitcast i8* [[CALL]] to %struct.T*
> >>> +// CHECK-NEXT:   ret %struct.T* [[RET]]
> >>>
> >>>  T* test4(V* x) { return dynamic_cast<T*>(x); }
> >>> -// CHECK: define %struct.T* @"\01?test4@@YAPAUT@@PAUV@@@Z"(%struct.V*
> >>> %x) #1 {
> >>> -// CHECK-NEXT: entry:
> >>> -// CHECK-NEXT:   %0 = bitcast %struct.V* %x to i8*
> >>> -// CHECK-NEXT:   %1 = tail call i8* @__RTDynamicCast(i8* %0, i32 0,
> i8*
> >>> bitcast (%"MSRTTITypeDescriptor\07"* @"\01??_R0?AUV@@@8" to i8*), i8*
> >>> bitcast (%"MSRTTITypeDescriptor\07"* @"\01??_R0?AUT@@@8" to i8*), i32
> 0) #2
> >>> -// CHECK-NEXT:   %2 = bitcast i8* %1 to %struct.T*
> >>> -// CHECK-NEXT:   ret %struct.T* %2
> >>> -// CHECK-NEXT: }
> >>> +// CHECK-LABEL: define %struct.T*
> >>> @"\01?test4@@YAPAUT@@PAUV@@@Z"(%struct.V* %x)
> >>> +// CHECK:        [[CAST:%.*]] = bitcast %struct.V* %x to i8*
> >>> +// CHECK-NEXT:   [[CALL:%.*]] = tail call i8* @__RTDynamicCast(i8*
> >>> [[CAST]], i32 0, i8* bitcast (%"MSRTTITypeDescriptor\07"*
> >>> @"\01??_R0?AUV@@@8" to i8*), i8* bitcast (%"MSRTTITypeDescriptor\07"*
> >>> @"\01??_R0?AUT@@@8" to i8*), i32 0)
> >>> +// CHECK-NEXT:   [[RET:%.*]] = bitcast i8* [[CALL]] to %struct.T*
> >>> +// CHECK-NEXT:   ret %struct.T* [[RET]]
> >>>
> >>>  T* test5(A* x) { return dynamic_cast<T*>(x); }
> >>> -// CHECK: define %struct.T* @"\01?test5@@YAPAUT@@PAUA@@@Z"(%struct.A*
> >>> %x) #1 {
> >>> -// CHECK-NEXT: entry:
> >>> -// CHECK-NEXT:   %0 = icmp eq %struct.A* %x, null
> >>> -// CHECK-NEXT:   br i1 %0, label %dynamic_cast.call, label
> >>> %dynamic_cast.valid
> >>> -// CHECK: dynamic_cast.valid:                               ; preds =
> >>> %entry
> >>> -// CHECK-NEXT:   %1 = bitcast %struct.A* %x to i8*
> >>> -// CHECK-NEXT:   %2 = bitcast %struct.A* %x to i8**
> >>> -// CHECK-NEXT:   %vbtable = load i8** %2, align 4
> >>> -// CHECK-NEXT:   %3 = getelementptr inbounds i8* %vbtable, i32 4
> >>> -// CHECK-NEXT:   %4 = bitcast i8* %3 to i32*
> >>> -// CHECK-NEXT:   %vbase_offs = load i32* %4, align 4
> >>> -// CHECK-NEXT:   %5 = getelementptr inbounds i8* %1, i32 %vbase_offs
> >>> -// CHECK-NEXT:   %6 = tail call i8* @__RTDynamicCast(i8* %5, i32
> >>> %vbase_offs, i8* bitcast (%"MSRTTITypeDescriptor\07"* @"\01??_R0?AUA@@@8"
> to
> >>> i8*), i8* bitcast (%"MSRTTITypeDescriptor\07"* @"\01??_R0?AUT@@@8" to
> i8*),
> >>> i32 0) #2
> >>> -// CHECK-NEXT:   %phitmp = bitcast i8* %6 to %struct.T*
> >>> -// CHECK-NEXT:   br label %dynamic_cast.call
> >>> -// CHECK: dynamic_cast.call:                                ; preds =
> >>> %dynamic_cast.valid, %entry
> >>> -// CHECK-NEXT:   %7 = phi %struct.T* [ %phitmp, %dynamic_cast.valid
> ], [
> >>> null, %entry ]
> >>> -// CHECK-NEXT:   ret %struct.T* %7
> >>> -// CHECK-NEXT: }
> >>> +// CHECK-LABEL: define %struct.T*
> >>> @"\01?test5@@YAPAUT@@PAUA@@@Z"(%struct.A* %x)
> >>> +// CHECK:        [[CHECK:%.*]] = icmp eq %struct.A* %x, null
> >>> +// CHECK-NEXT:   br i1 [[CHECK]]
> >>> +// CHECK:        [[VOIDP:%.*]] = bitcast %struct.A* %x to i8*
> >>> +// CHECK-NEXT:   [[BITCAST:%.*]] = bitcast %struct.A* %x to i8**
> >>> +// CHECK-NEXT:   [[VBTBL:%.*]] = load i8** [[BITCAST]], align 4
> >>> +// CHECK-NEXT:   [[VBOFFP:%.*]] = getelementptr inbounds i8*
> [[VBTBL]],
> >>> i32 4
> >>> +// CHECK-NEXT:   [[VBOFFPCAST:%.*]] = bitcast i8* [[VBOFFP]] to i32*
> >>> +// CHECK-NEXT:   [[VBOFFS:%.*]] = load i32* [[VBOFFPCAST:%.*]], align
> 4
> >>> +// CHECK-NEXT:   [[ADJ:%.*]] = getelementptr inbounds i8* [[VOIDP]],
> i32
> >>> [[VBOFFS]]
> >>> +// CHECK-NEXT:   [[CALL:%.*]] = tail call i8* @__RTDynamicCast(i8*
> >>> [[ADJ]], i32 [[VBOFFS]], i8* bitcast (%"MSRTTITypeDescriptor\07"*
> >>> @"\01??_R0?AUA@@@8" to i8*), i8* bitcast (%"MSRTTITypeDescriptor\07"*
> >>> @"\01??_R0?AUT@@@8" to i8*), i32 0)
> >>> +// CHECK-NEXT:   [[RES:%.*]] = bitcast i8* [[CALL]] to %struct.T*
> >>> +// CHECK-NEXT:   br label
> >>> +// CHECK:        [[RET:%.*]] = phi %struct.T*
> >>> +// CHECK-NEXT:   ret %struct.T* [[RET]]
> >>>
> >>>  T* test6(B* x) { return dynamic_cast<T*>(x); }
> >>> -// CHECK: define %struct.T* @"\01?test6@@YAPAUT@@PAUB@@@Z"(%struct.B*
> >>> %x) #1 {
> >>> -// CHECK-NEXT: entry:
> >>> -// CHECK-NEXT:   %0 = icmp eq %struct.B* %x, null
> >>> -// CHECK-NEXT:   br i1 %0, label %dynamic_cast.call, label
> >>> %dynamic_cast.valid
> >>> -// CHECK: dynamic_cast.valid:                               ; preds =
> >>> %entry
> >>> -// CHECK-NEXT:   %1 = getelementptr inbounds %struct.B* %x, i32 0, i32
> >>> 0, i32 0
> >>> -// CHECK-NEXT:   %vbptr = getelementptr inbounds i8* %1, i32 4
> >>> -// CHECK-NEXT:   %2 = bitcast i8* %vbptr to i8**
> >>> -// CHECK-NEXT:   %vbtable = load i8** %2, align 4
> >>> -// CHECK-NEXT:   %3 = getelementptr inbounds i8* %vbtable, i32 4
> >>> -// CHECK-NEXT:   %4 = bitcast i8* %3 to i32*
> >>> -// CHECK-NEXT:   %vbase_offs = load i32* %4, align 4
> >>> -// CHECK-NEXT:   %5 = add nsw i32 %vbase_offs, 4
> >>> -// CHECK-NEXT:   %6 = getelementptr inbounds i8* %1, i32 %5
> >>> -// CHECK-NEXT:   %7 = tail call i8* @__RTDynamicCast(i8* %6, i32 %5,
> i8*
> >>> bitcast (%"MSRTTITypeDescriptor\07"* @"\01??_R0?AUB@@@8" to i8*), i8*
> >>> bitcast (%"MSRTTITypeDescriptor\07"* @"\01??_R0?AUT@@@8" to i8*), i32
> 0) #2
> >>> -// CHECK-NEXT:   %phitmp = bitcast i8* %7 to %struct.T*
> >>> -// CHECK-NEXT:   br label %dynamic_cast.call
> >>> -// CHECK: dynamic_cast.call:                                ; preds =
> >>> %dynamic_cast.valid, %entry
> >>> -// CHECK-NEXT:   %8 = phi %struct.T* [ %phitmp, %dynamic_cast.valid
> ], [
> >>> null, %entry ]
> >>> -// CHECK-NEXT:   ret %struct.T* %8
> >>> -// CHECK-NEXT: }
> >>> +// CHECK-LABEL: define %struct.T*
> >>> @"\01?test6@@YAPAUT@@PAUB@@@Z"(%struct.B* %x)
> >>> +// CHECK:        [[CHECK:%.*]] = icmp eq %struct.B* %x, null
> >>> +// CHECK-NEXT:   br i1 [[CHECK]]
> >>> +// CHECK:        [[CAST:%.*]] = getelementptr inbounds %struct.B* %x,
> >>> i32 0, i32 0, i32 0
> >>> +// CHECK-NEXT:   [[VBPTR:%.*]] = getelementptr inbounds i8* [[CAST]],
> >>> i32 4
> >>> +// CHECK-NEXT:   [[BITCAST:%.*]] = bitcast i8* [[VBPTR]] to i8**
> >>> +// CHECK-NEXT:   [[VBTBL:%.*]] = load i8** [[BITCAST]], align 4
> >>> +// CHECK-NEXT:   [[VBOFFP:%.*]] = getelementptr inbounds i8*
> [[VBTBL]],
> >>> i32 4
> >>> +// CHECK-NEXT:   [[VBOFFPCAST:%.*]] = bitcast i8* [[VBOFFP]] to i32*
> >>> +// CHECK-NEXT:   [[VBOFFS:%.*]] = load i32* [[VBOFFPCAST:%.*]], align
> 4
> >>> +// CHECK-NEXT:   [[DELTA:%.*]] = add nsw i32 [[VBOFFS]], 4
> >>> +// CHECK-NEXT:   [[ADJ:%.*]] = getelementptr inbounds i8* [[CAST]],
> i32
> >>> [[DELTA]]
> >>> +// CHECK-NEXT:   [[CALL:%.*]] = tail call i8* @__RTDynamicCast(i8*
> >>> [[ADJ]], i32 [[DELTA]], i8* bitcast (%"MSRTTITypeDescriptor\07"*
> >>> @"\01??_R0?AUB@@@8" to i8*), i8* bitcast (%"MSRTTITypeDescriptor\07"*
> >>> @"\01??_R0?AUT@@@8" to i8*), i32 0)
> >>> +// CHECK-NEXT:   [[RES:%.*]] = bitcast i8* [[CALL]] to %struct.T*
> >>> +// CHECK-NEXT:   br label
> >>> +// CHECK:        [[RET:%.*]] = phi %struct.T*
> >>> +// CHECK-NEXT:   ret %struct.T* [[RET]]
> >>>
> >>>  void* test7(V* x) { return dynamic_cast<void*>(x); }
> >>> -// CHECK: define i8* @"\01?test7@@YAPAXPAUV@@@Z"(%struct.V* %x) #1 {
> >>> -// CHECK-NEXT: entry:
> >>> -// CHECK-NEXT:   %0 = bitcast %struct.V* %x to i8*
> >>> -// CHECK-NEXT:   %1 = tail call i8* @__RTCastToVoid(i8* %0) #2
> >>> -// CHECK-NEXT:   ret i8* %1
> >>> -// CHECK-NEXT: }
> >>> +// CHECK-LABEL: define i8* @"\01?test7@@YAPAXPAUV@@@Z"(%struct.V* %x)
> >>> +// CHECK:        [[CAST:%.*]] = bitcast %struct.V* %x to i8*
> >>> +// CHECK-NEXT:   [[RET:%.*]] = tail call i8* @__RTCastToVoid(i8*
> >>> [[CAST]])
> >>> +// CHECK-NEXT:   ret i8* [[RET]]
> >>>
> >>>  void* test8(A* x) { return dynamic_cast<void*>(x); }
> >>> -// CHECK: define i8* @"\01?test8@@YAPAXPAUA@@@Z"(%struct.A* %x) #1 {
> >>> -// CHECK-NEXT: entry:
> >>> -// CHECK-NEXT:   %0 = icmp eq %struct.A* %x, null
> >>> -// CHECK-NEXT:   br i1 %0, label %dynamic_cast.call, label
> >>> %dynamic_cast.valid
> >>> -// CHECK: dynamic_cast.valid:                               ; preds =
> >>> %entry
> >>> -// CHECK-NEXT:   %1 = bitcast %struct.A* %x to i8*
> >>> -// CHECK-NEXT:   %2 = bitcast %struct.A* %x to i8**
> >>> -// CHECK-NEXT:   %vbtable = load i8** %2, align 4
> >>> -// CHECK-NEXT:   %3 = getelementptr inbounds i8* %vbtable, i32 4
> >>> -// CHECK-NEXT:   %4 = bitcast i8* %3 to i32*
> >>> -// CHECK-NEXT:   %vbase_offs = load i32* %4, align 4
> >>> -// CHECK-NEXT:   %5 = getelementptr inbounds i8* %1, i32 %vbase_offs
> >>> -// CHECK-NEXT:   %6 = tail call i8* @__RTCastToVoid(i8* %5) #2
> >>> -// CHECK-NEXT:   br label %dynamic_cast.call
> >>> -// CHECK: dynamic_cast.call:                                ; preds =
> >>> %dynamic_cast.valid, %entry
> >>> -// CHECK-NEXT:   %7 = phi i8* [ %6, %dynamic_cast.valid ], [ null,
> >>> %entry ]
> >>> -// CHECK-NEXT:   ret i8* %7
> >>> -// CHECK-NEXT: }
> >>> +// CHECK-LABEL: define i8* @"\01?test8@@YAPAXPAUA@@@Z"(%struct.A* %x)
> >>> +// CHECK:        [[CHECK:%.*]] = icmp eq %struct.A* %x, null
> >>> +// CHECK-NEXT:   br i1 [[CHECK]]
> >>> +// CHECK:        [[VOIDP:%.*]] = bitcast %struct.A* %x to i8*
> >>> +// CHECK-NEXT:   [[BITCAST:%.*]] = bitcast %struct.A* %x to i8**
> >>> +// CHECK-NEXT:   [[VBTBL:%.*]] = load i8** [[BITCAST]], align 4
> >>> +// CHECK-NEXT:   [[VBOFFP:%.*]] = getelementptr inbounds i8*
> [[VBTBL]],
> >>> i32 4
> >>> +// CHECK-NEXT:   [[VBOFFPCAST:%.*]] = bitcast i8* [[VBOFFP]] to i32*
> >>> +// CHECK-NEXT:   [[VBOFFS:%.*]] = load i32* [[VBOFFPCAST:%.*]], align
> 4
> >>> +// CHECK-NEXT:   [[ADJ:%.*]] = getelementptr inbounds i8* [[VOIDP]],
> i32
> >>> [[VBOFFS]]
> >>> +// CHECK-NEXT:   [[RES:%.*]] = tail call i8* @__RTCastToVoid(i8*
> >>> [[ADJ]])
> >>> +// CHECK-NEXT:   br label
> >>> +// CHECK:        [[RET:%.*]] = phi i8*
> >>> +// CHECK-NEXT:   ret i8* [[RET]]
> >>>
> >>>  void* test9(B* x) { return dynamic_cast<void*>(x); }
> >>> -// CHECK: define i8* @"\01?test9@@YAPAXPAUB@@@Z"(%struct.B* %x) #1 {
> >>> -// CHECK-NEXT: entry:
> >>> -// CHECK-NEXT:   %0 = icmp eq %struct.B* %x, null
> >>> -// CHECK-NEXT:   br i1 %0, label %dynamic_cast.call, label
> >>> %dynamic_cast.valid
> >>> -// CHECK: dynamic_cast.valid:                               ; preds =
> >>> %entry
> >>> -// CHECK-NEXT:   %1 = getelementptr inbounds %struct.B* %x, i32 0, i32
> >>> 0, i32 0
> >>> -// CHECK-NEXT:   %vbptr = getelementptr inbounds i8* %1, i32 4
> >>> -// CHECK-NEXT:   %2 = bitcast i8* %vbptr to i8**
> >>> -// CHECK-NEXT:   %vbtable = load i8** %2, align 4
> >>> -// CHECK-NEXT:   %3 = getelementptr inbounds i8* %vbtable, i32 4
> >>> -// CHECK-NEXT:   %4 = bitcast i8* %3 to i32*
> >>> -// CHECK-NEXT:   %vbase_offs = load i32* %4, align 4
> >>> -// CHECK-NEXT:   %5 = add nsw i32 %vbase_offs, 4
> >>> -// CHECK-NEXT:   %6 = getelementptr inbounds i8* %1, i32 %5
> >>> -// CHECK-NEXT:   %7 = tail call i8* @__RTCastToVoid(i8* %6) #2
> >>> -// CHECK-NEXT:   br label %dynamic_cast.call
> >>> -// CHECK: dynamic_cast.call:                                ; preds =
> >>> %dynamic_cast.valid, %entry
> >>> -// CHECK-NEXT:   %8 = phi i8* [ %7, %dynamic_cast.valid ], [ null,
> >>> %entry ]
> >>> -// CHECK-NEXT:   ret i8* %8
> >>> -// CHECK-NEXT: }
> >>> +// CHECK-LABEL: define i8* @"\01?test9@@YAPAXPAUB@@@Z"(%struct.B* %x)
> >>> +// CHECK:        [[CHECK:%.*]] = icmp eq %struct.B* %x, null
> >>> +// CHECK-NEXT:   br i1 [[CHECK]]
> >>> +// CHECK:        [[CAST:%.*]] = getelementptr inbounds %struct.B* %x,
> >>> i32 0, i32 0, i32 0
> >>> +// CHECK-NEXT:   [[VBPTR:%.*]] = getelementptr inbounds i8* [[CAST]],
> >>> i32 4
> >>> +// CHECK-NEXT:   [[BITCAST:%.*]] = bitcast i8* [[VBPTR]] to i8**
> >>> +// CHECK-NEXT:   [[VBTBL:%.*]] = load i8** [[BITCAST]], align 4
> >>> +// CHECK-NEXT:   [[VBOFFP:%.*]] = getelementptr inbounds i8*
> [[VBTBL]],
> >>> i32 4
> >>> +// CHECK-NEXT:   [[VBOFFPCAST:%.*]] = bitcast i8* [[VBOFFP]] to i32*
> >>> +// CHECK-NEXT:   [[VBOFFS:%.*]] = load i32* [[VBOFFPCAST:%.*]], align
> 4
> >>> +// CHECK-NEXT:   [[DELTA:%.*]] = add nsw i32 [[VBOFFS]], 4
> >>> +// CHECK-NEXT:   [[ADJ:%.*]] = getelementptr inbounds i8* [[CAST]],
> i32
> >>> [[DELTA]]
> >>> +// CHECK-NEXT:   [[CALL:%.*]] = tail call i8* @__RTCastToVoid(i8*
> >>> [[ADJ]])
> >>> +// CHECK-NEXT:   br label
> >>> +// CHECK:        [[RET:%.*]] = phi i8*
> >>> +// CHECK-NEXT:   ret i8* [[RET]]
> >>> +
> >>>
> >>> Modified: cfe/trunk/test/CodeGenCXX/microsoft-abi-typeid.cpp
> >>> URL:
> >>>
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/microsoft-abi-typeid.cpp?rev=211473&r1=211472&r2=211473&view=diff
> >>>
> >>>
> ==============================================================================
> >>> --- cfe/trunk/test/CodeGenCXX/microsoft-abi-typeid.cpp (original)
> >>> +++ cfe/trunk/test/CodeGenCXX/microsoft-abi-typeid.cpp Sun Jun 22
> >>> 14:05:33 2014
> >>> @@ -1,58 +1,45 @@
> >>> -// RUN: %clang_cc1 -emit-llvm -O2 -optzns -o - -triple=i386-pc-win32
> >>> 2>/dev/null %s | FileCheck %s
> >>> -// REQUIRES: asserts
> >>> +// RUN: %clang_cc1 -emit-llvm -O1 -o - -triple=i386-pc-win32 %s |
> >>> FileCheck %s
> >>>
> >>> -struct type_info { const char* raw_name() const; };
> >>> +struct type_info;
> >>>  namespace std { using ::type_info; }
> >>>
> >>> -struct V { virtual void f() {}; };
> >>> -struct A : virtual V {};
> >>> +struct V { virtual void f(); };
> >>> +struct A : virtual V { A(); };
> >>>
> >>> -A a;
> >>> -int b;
> >>> +extern A a;
> >>> +extern int b;
> >>>  A* fn();
> >>>
> >>>  const std::type_info* test0_typeid() { return &typeid(int); }
> >>> -// CHECK: define %struct.type_info*
> >>> @"\01?test0_typeid@@YAPBUtype_info@@XZ"() #0 {
> >>> -// CHECK-NEXT: entry:
> >>> -// CHECK-NEXT:   ret %struct.type_info* bitcast
> >>> (%"MSRTTITypeDescriptor\02"* @"\01??_R0H at 8" to %struct.type_info*)
> >>> -// CHECK-NEXT: }
> >>> +// CHECK-LABEL: define %struct.type_info*
> >>> @"\01?test0_typeid@@YAPBUtype_info@@XZ"()
> >>> +// CHECK:   ret %struct.type_info* bitcast
> (%"MSRTTITypeDescriptor\02"*
> >>> @"\01??_R0H at 8" to %struct.type_info*)
> >>>
> >>>  const std::type_info* test1_typeid() { return &typeid(A); }
> >>> -// CHECK: define %struct.type_info*
> >>> @"\01?test1_typeid@@YAPBUtype_info@@XZ"() #0 {
> >>> -// CHECK-NEXT: entry:
> >>> -// CHECK-NEXT:   ret %struct.type_info* bitcast
> >>> (%"MSRTTITypeDescriptor\07"* @"\01??_R0?AUA@@@8" to
> %struct.type_info*)
> >>> -// CHECK-NEXT: }
> >>> +// CHECK-LABEL: define %struct.type_info*
> >>> @"\01?test1_typeid@@YAPBUtype_info@@XZ"()
> >>> +// CHECK:   ret %struct.type_info* bitcast
> (%"MSRTTITypeDescriptor\07"*
> >>> @"\01??_R0?AUA@@@8" to %struct.type_info*)
> >>>
> >>>  const std::type_info* test2_typeid() { return &typeid(&a); }
> >>> -// CHECK: define %struct.type_info*
> >>> @"\01?test2_typeid@@YAPBUtype_info@@XZ"() #0 {
> >>> -// CHECK-NEXT: entry:
> >>> -// CHECK-NEXT:   ret %struct.type_info* bitcast
> >>> (%"MSRTTITypeDescriptor\07"* @"\01??_R0PAUA@@@8" to
> %struct.type_info*)
> >>> -// CHECK-NEXT: }
> >>> +// CHECK-LABEL: define %struct.type_info*
> >>> @"\01?test2_typeid@@YAPBUtype_info@@XZ"()
> >>> +// CHECK:   ret %struct.type_info* bitcast
> (%"MSRTTITypeDescriptor\07"*
> >>> @"\01??_R0PAUA@@@8" to %struct.type_info*)
> >>>
> >>>  const std::type_info* test3_typeid() { return &typeid(*fn()); }
> >>> -// CHECK: define %struct.type_info*
> >>> @"\01?test3_typeid@@YAPBUtype_info@@XZ"() #1 {
> >>> -// CHECK-NEXT: entry:
> >>> -// CHECK-NEXT:   %call = tail call %struct.A* @"\01?fn@@YAPAUA@@XZ"()
> #3
> >>> -// CHECK-NEXT:   %0 = icmp eq %struct.A* %call, null
> >>> -// CHECK-NEXT:   br i1 %0, label %type_id.call, label %type_id.valid
> >>> -// CHECK: type_id.valid:                                    ; preds =
> >>> %entry
> >>> -// CHECK-NEXT:   %1 = bitcast %struct.A* %call to i8*
> >>> -// CHECK-NEXT:   %2 = bitcast %struct.A* %call to i8**
> >>> -// CHECK-NEXT:   %vbtable = load i8** %2, align 4
> >>> -// CHECK-NEXT:   %3 = getelementptr inbounds i8* %vbtable, i32 4
> >>> -// CHECK-NEXT:   %4 = bitcast i8* %3 to i32*
> >>> -// CHECK-NEXT:   %vbase_offs = load i32* %4, align 4
> >>> -// CHECK-NEXT:   %5 = getelementptr inbounds i8* %1, i32 %vbase_offs
> >>> -// CHECK-NEXT:   br label %type_id.call
> >>> -// CHECK: type_id.call:                                     ; preds =
> >>> %type_id.valid, %entry
> >>> -// CHECK-NEXT:   %6 = phi i8* [ %5, %type_id.valid ], [ null, %entry ]
> >>> -// CHECK-NEXT:   %7 = tail call i8* @__RTtypeid(i8* %6) #3
> >>> -// CHECK-NEXT:   %8 = bitcast i8* %7 to %struct.type_info*
> >>> -// CHECK-NEXT:   ret %struct.type_info* %8
> >>> -// CHECK-NEXT: }
> >>> +// CHECK-LABEL: define %struct.type_info*
> >>> @"\01?test3_typeid@@YAPBUtype_info@@XZ"()
> >>> +// CHECK:        [[CALL:%.*]] = tail call %struct.A*
> >>> @"\01?fn@@YAPAUA@@XZ"()
> >>> +// CHECK-NEXT:   [[CMP:%.*]] = icmp eq %struct.A* [[CALL]], null
> >>> +// CHECK-NEXT:   br i1 [[CMP]]
> >>> +// CHECK:        tail call i8* @__RTtypeid(i8* null)
> >>> +// CHECK-NEXT:   unreachable
> >>> +// CHECK:        [[THIS:%.*]] = bitcast %struct.A* [[CALL]] to i8*
> >>> +// CHECK-NEXT:   [[VBTBLP:%.*]] = bitcast %struct.A* [[CALL]] to i8**
> >>> +// CHECK-NEXT:   [[VBTBL:%.*]] = load i8** [[VBTBLP]], align 4
> >>> +// CHECK-NEXT:   [[VBSLOT:%.*]] = getelementptr inbounds i8*
> [[VBTBL]],
> >>> i32 4
> >>> +// CHECK-NEXT:   [[VBITCST:%.*]] = bitcast i8* [[VBSLOT]] to i32*
> >>> +// CHECK-NEXT:   [[VBASE_OFFS:%.*]] = load i32* [[VBITCST]], align 4
> >>> +// CHECK-NEXT:   [[ADJ:%.*]] = getelementptr inbounds i8* [[THIS]],
> i32
> >>> [[VBASE_OFFS]]
> >>> +// CHECK-NEXT:   [[RT:%.*]] = tail call i8* @__RTtypeid(i8* [[ADJ]])
> >>> +// CHECK-NEXT:   [[RET:%.*]] = bitcast i8* [[RT]] to
> %struct.type_info*
> >>> +// CHECK-NEXT:   ret %struct.type_info* [[RET]]
> >>>
> >>>  const std::type_info* test4_typeid() { return &typeid(b); }
> >>> -// CHECK: define %struct.type_info*
> >>> @"\01?test4_typeid@@YAPBUtype_info@@XZ"() #0 {
> >>> -// CHECK-NEXT: entry:
> >>> -// CHECK-NEXT:   ret %struct.type_info* bitcast
> >>> (%"MSRTTITypeDescriptor\02"* @"\01??_R0H at 8" to %struct.type_info*)
> >>> -// CHECK-NEXT: }
> >>> +// CHECK: define %struct.type_info*
> >>> @"\01?test4_typeid@@YAPBUtype_info@@XZ"()
> >>> +// CHECK:   ret %struct.type_info* bitcast
> (%"MSRTTITypeDescriptor\02"*
> >>> @"\01??_R0H at 8" to %struct.type_info*)
> >>>
> >>>
> >>> _______________________________________________
> >>> cfe-commits mailing list
> >>> cfe-commits at cs.uiuc.edu
> >>> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
> >
> >
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20140623/7e768daa/attachment.html>


More information about the cfe-commits mailing list