llvm::Value * CodeGenFunction::EmitCXXTypeidExpr(const CXXTypeidExpr *E) { QualType Ty = E->getType(); const llvm::Type *LTy = ConvertType(Ty)->getPointerTo(); if (E->isTypeOperand()) { Ty = E->getTypeOperand(); CanQualType CanTy = CGM.getContext().getCanonicalType(Ty); Ty = CanTy.getUnqualifiedType().getNonReferenceType(); if (const RecordType *RT = Ty->getAs<RecordType>()) { const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl()); if (RD->isPolymorphic()) return Builder.CreateBitCast(CGM.GenerateRttiRef(RD), LTy); return Builder.CreateBitCast(CGM.GenerateRtti(RD), LTy); } return Builder.CreateBitCast(CGM.GenerateRttiNonClass(Ty), LTy); } Expr *subE = E->getExprOperand(); Ty = subE->getType(); CanQualType CanTy = CGM.getContext().getCanonicalType(Ty); Ty = CanTy.getUnqualifiedType().getNonReferenceType(); if (const RecordType *RT = Ty->getAs<RecordType>()) { const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl()); if (RD->isPolymorphic()) { // FIXME: if subE is an lvalue do LValue Obj = EmitLValue(subE); llvm::Value *This = Obj.getAddress(); LTy = LTy->getPointerTo()->getPointerTo(); llvm::Value *V = Builder.CreateBitCast(This, LTy); // We need to do a zero check for *p, unless it has NonNullAttr. // FIXME: PointerType->hasAttr<NonNullAttr>() bool CanBeZero = false; if (UnaryOperator *UO = dyn_cast<UnaryOperator>(subE->IgnoreParens())) if (UO->getOpcode() == UnaryOperator::Deref) CanBeZero = true; if (CanBeZero) { llvm::BasicBlock *NonZeroBlock = createBasicBlock(); llvm::BasicBlock *ZeroBlock = createBasicBlock(); llvm::Value *Zero = llvm::Constant::getNullValue(LTy); Builder.CreateCondBr(Builder.CreateICmpNE(V, Zero), NonZeroBlock, ZeroBlock); EmitBlock(ZeroBlock); /// Call __cxa_bad_typeid const llvm::Type *ResultType = llvm::Type::getVoidTy(VMContext); const llvm::FunctionType *FTy; FTy = llvm::FunctionType::get(ResultType, false); llvm::Value *F = CGM.CreateRuntimeFunction(FTy, "__cxa_bad_typeid"); Builder.CreateCall(F)->setDoesNotReturn(); Builder.CreateUnreachable(); EmitBlock(NonZeroBlock); } V = Builder.CreateLoad(V, "vtable"); V = Builder.CreateConstInBoundsGEP1_64(V, -1ULL); V = Builder.CreateLoad(V); return V; } return Builder.CreateBitCast(CGM.GenerateRtti(RD), LTy); } return Builder.CreateBitCast(CGM.GenerateRttiNonClass(Ty), LTy); }
bool CXXConstructorDecl::isCopyConstructorLikeSpecialization() const { if ((getNumParams() < 1) || (getNumParams() > 1 && !getParamDecl(1)->hasDefaultArg()) || (getPrimaryTemplate() == 0) || (getDescribedFunctionTemplate() != 0)) return false; const ParmVarDecl *Param = getParamDecl(0); ASTContext &Context = getASTContext(); CanQualType ParamType = Context.getCanonicalType(Param->getType()); // Strip off the lvalue reference, if any. if (CanQual<LValueReferenceType> ParamRefType = ParamType->getAs<LValueReferenceType>()) ParamType = ParamRefType->getPointeeType(); // Is it the same as our our class type? CanQualType ClassTy = Context.getCanonicalType(Context.getTagDeclType(getParent())); if (ParamType.getUnqualifiedType() != ClassTy) return false; return true; }
bool CXXConstructorDecl::isCopyConstructor(unsigned &TypeQuals) const { // C++ [class.copy]p2: // A non-template constructor for class X is a copy constructor // if its first parameter is of type X&, const X&, volatile X& or // const volatile X&, and either there are no other parameters // or else all other parameters have default arguments (8.3.6). if ((getNumParams() < 1) || (getNumParams() > 1 && !getParamDecl(1)->hasDefaultArg()) || (getPrimaryTemplate() != 0) || (getDescribedFunctionTemplate() != 0)) return false; const ParmVarDecl *Param = getParamDecl(0); // Do we have a reference type? Rvalue references don't count. const LValueReferenceType *ParamRefType = Param->getType()->getAs<LValueReferenceType>(); if (!ParamRefType) return false; // Is it a reference to our class type? ASTContext &Context = getASTContext(); CanQualType PointeeType = Context.getCanonicalType(ParamRefType->getPointeeType()); CanQualType ClassTy = Context.getCanonicalType(Context.getTagDeclType(getParent())); if (PointeeType.getUnqualifiedType() != ClassTy) return false; // FIXME: other qualifiers? // We have a copy constructor. TypeQuals = PointeeType.getCVRQualifiers(); return true; }
/// isAmbiguous - Determines whether the set of paths provided is /// ambiguous, i.e., there are two or more paths that refer to /// different base class subobjects of the same type. BaseType must be /// an unqualified, canonical class type. bool CXXBasePaths::isAmbiguous(CanQualType BaseType) { BaseType = BaseType.getUnqualifiedType(); std::pair<bool, unsigned>& Subobjects = ClassSubobjects[BaseType]; return Subobjects.second + (Subobjects.first? 1 : 0) > 1; }
llvm::Value *CodeGenFunction::EmitDynamicCast(llvm::Value *V, const CXXDynamicCastExpr *DCE) { QualType CastTy = DCE->getTypeAsWritten(); QualType InnerType = CastTy->getPointeeType(); QualType ArgTy = DCE->getSubExpr()->getType(); const llvm::Type *LArgTy = ConvertType(ArgTy); const llvm::Type *LTy = ConvertType(DCE->getType()); bool CanBeZero = false; bool ToVoid = false; bool ThrowOnBad = false; if (CastTy->isPointerType()) { // FIXME: if PointerType->hasAttr<NonNullAttr>(), we don't set this CanBeZero = true; if (InnerType->isVoidType()) ToVoid = true; } else { LTy = LTy->getPointerTo(); ThrowOnBad = true; } CXXRecordDecl *SrcTy; QualType Ty = ArgTy; if (ArgTy.getTypePtr()->isPointerType() || ArgTy.getTypePtr()->isReferenceType()) Ty = Ty.getTypePtr()->getPointeeType(); CanQualType CanTy = CGM.getContext().getCanonicalType(Ty); Ty = CanTy.getUnqualifiedType(); SrcTy = cast<CXXRecordDecl>(Ty->getAs<RecordType>()->getDecl()); llvm::BasicBlock *ContBlock = createBasicBlock(); llvm::BasicBlock *NullBlock = 0; llvm::BasicBlock *NonZeroBlock = 0; if (CanBeZero) { NonZeroBlock = createBasicBlock(); NullBlock = createBasicBlock(); llvm::Value *Zero = llvm::Constant::getNullValue(LArgTy); Builder.CreateCondBr(Builder.CreateICmpNE(V, Zero), NonZeroBlock, NullBlock); EmitBlock(NonZeroBlock); } llvm::BasicBlock *BadCastBlock = 0; const llvm::Type *PtrDiffTy = ConvertType(getContext().getSizeType()); // See if this is a dynamic_cast(void*) if (ToVoid) { llvm::Value *This = V; V = Builder.CreateBitCast(This, PtrDiffTy->getPointerTo()->getPointerTo()); V = Builder.CreateLoad(V, "vtable"); V = Builder.CreateConstInBoundsGEP1_64(V, -2ULL); V = Builder.CreateLoad(V, "offset to top"); This = Builder.CreateBitCast(This, llvm::Type::getInt8PtrTy(VMContext)); V = Builder.CreateInBoundsGEP(This, V); V = Builder.CreateBitCast(V, LTy); } else { /// Call __dynamic_cast const llvm::Type *ResultType = llvm::Type::getInt8PtrTy(VMContext); const llvm::FunctionType *FTy; std::vector<const llvm::Type*> ArgTys; const llvm::Type *PtrToInt8Ty = llvm::Type::getInt8Ty(VMContext)->getPointerTo(); ArgTys.push_back(PtrToInt8Ty); ArgTys.push_back(PtrToInt8Ty); ArgTys.push_back(PtrToInt8Ty); ArgTys.push_back(PtrDiffTy); FTy = llvm::FunctionType::get(ResultType, ArgTys, false); CXXRecordDecl *DstTy; Ty = CastTy.getTypePtr()->getPointeeType(); CanTy = CGM.getContext().getCanonicalType(Ty); Ty = CanTy.getUnqualifiedType(); DstTy = cast<CXXRecordDecl>(Ty->getAs<RecordType>()->getDecl()); // FIXME: Calculate better hint. llvm::Value *hint = llvm::ConstantInt::get(PtrDiffTy, -1ULL); llvm::Value *SrcArg = CGM.GenerateRttiRef(SrcTy); llvm::Value *DstArg = CGM.GenerateRttiRef(DstTy); V = Builder.CreateBitCast(V, PtrToInt8Ty); V = Builder.CreateCall4(CGM.CreateRuntimeFunction(FTy, "__dynamic_cast"), V, SrcArg, DstArg, hint); V = Builder.CreateBitCast(V, LTy); if (ThrowOnBad) { BadCastBlock = createBasicBlock(); llvm::Value *Zero = llvm::Constant::getNullValue(LTy); Builder.CreateCondBr(Builder.CreateICmpNE(V, Zero), ContBlock, BadCastBlock); EmitBlock(BadCastBlock); /// Call __cxa_bad_cast ResultType = llvm::Type::getVoidTy(VMContext); const llvm::FunctionType *FBadTy; FBadTy = llvm::FunctionType::get(ResultType, false); llvm::Value *F = CGM.CreateRuntimeFunction(FBadTy, "__cxa_bad_cast"); Builder.CreateCall(F)->setDoesNotReturn(); Builder.CreateUnreachable(); } } if (CanBeZero) { Builder.CreateBr(ContBlock); EmitBlock(NullBlock); Builder.CreateBr(ContBlock); } EmitBlock(ContBlock); if (CanBeZero) { llvm::PHINode *PHI = Builder.CreatePHI(LTy); PHI->reserveOperandSpace(2); PHI->addIncoming(V, NonZeroBlock); PHI->addIncoming(llvm::Constant::getNullValue(LTy), NullBlock); V = PHI; } return V; }
DeclarationName DeclarationNameTable::getCXXDestructorName(CanQualType Ty) { return getCXXSpecialName(DeclarationName::CXXDestructorName, Ty.getUnqualifiedType()); }