/// GenerateCXXAggrDestructorHelper - Generates a helper function which when /// invoked, calls the default destructor on array elements in reverse order of /// construction. llvm::Function * CodeGenFunction::GenerateCXXAggrDestructorHelper(const CXXDestructorDecl *D, const ArrayType *Array, llvm::Value *This) { FunctionArgList Args; ImplicitParamDecl *Dst = ImplicitParamDecl::Create(getContext(), 0, SourceLocation(), 0, getContext().getPointerType(getContext().VoidTy)); Args.push_back(std::make_pair(Dst, Dst->getType())); const CGFunctionInfo &FI = CGM.getTypes().getFunctionInfo(getContext().VoidTy, Args, FunctionType::ExtInfo()); const llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI, false); llvm::Function *Fn = CreateGlobalInitOrDestructFunction(CGM, FTy, "__cxx_global_array_dtor"); StartFunction(GlobalDecl(), getContext().VoidTy, Fn, Args, SourceLocation()); QualType BaseElementTy = getContext().getBaseElementType(Array); const llvm::Type *BasePtr = ConvertType(BaseElementTy)->getPointerTo(); llvm::Value *BaseAddrPtr = Builder.CreateBitCast(This, BasePtr); EmitCXXAggrDestructorCall(D, Array, BaseAddrPtr); FinishFunction(); return Fn; }
void ObjCMethodDecl::createImplicitParams(ASTContext &Context, const ObjCInterfaceDecl *OID) { QualType selfTy; if (isInstanceMethod()) { // There may be no interface context due to error in declaration // of the interface (which has been reported). Recover gracefully. if (OID) { selfTy = Context.getObjCInterfaceType(OID); selfTy = Context.getObjCObjectPointerType(selfTy); } else { selfTy = Context.getObjCIdType(); } } else // we have a factory method. selfTy = Context.getObjCClassType(); bool selfIsPseudoStrong = false; bool selfIsConsumed = false; if (Context.getLangOpts().ObjCAutoRefCount) { if (isInstanceMethod()) { selfIsConsumed = hasAttr<NSConsumesSelfAttr>(); // 'self' is always __strong. It's actually pseudo-strong except // in init methods (or methods labeled ns_consumes_self), though. Qualifiers qs; qs.setObjCLifetime(Qualifiers::OCL_Strong); selfTy = Context.getQualifiedType(selfTy, qs); // In addition, 'self' is const unless this is an init method. if (getMethodFamily() != OMF_init && !selfIsConsumed) { selfTy = selfTy.withConst(); selfIsPseudoStrong = true; } } else { assert(isClassMethod()); // 'self' is always const in class methods. selfTy = selfTy.withConst(); selfIsPseudoStrong = true; } } ImplicitParamDecl *self = ImplicitParamDecl::Create(Context, this, SourceLocation(), &Context.Idents.get("self"), selfTy); setSelfDecl(self); if (selfIsConsumed) self->addAttr(new (Context) NSConsumedAttr(SourceLocation(), Context)); if (selfIsPseudoStrong) self->setARCPseudoStrong(true); setCmdDecl(ImplicitParamDecl::Create(Context, this, SourceLocation(), &Context.Idents.get("_cmd"), Context.getObjCSelType())); }
void ItaniumCXXABI::BuildInstanceFunctionParams(CodeGenFunction &CGF, QualType &ResTy, FunctionArgList &Params) { /// Create the 'this' variable. BuildThisParam(CGF, Params); const CXXMethodDecl *MD = cast<CXXMethodDecl>(CGF.CurGD.getDecl()); assert(MD->isInstance()); // Check if we need a VTT parameter as well. if (CodeGenVTables::needsVTTParameter(CGF.CurGD)) { ASTContext &Context = getContext(); // FIXME: avoid the fake decl QualType T = Context.getPointerType(Context.VoidPtrTy); ImplicitParamDecl *VTTDecl = ImplicitParamDecl::Create(Context, 0, MD->getLocation(), &Context.Idents.get("vtt"), T); Params.push_back(std::make_pair(VTTDecl, VTTDecl->getType())); getVTTDecl(CGF) = VTTDecl; } }
llvm::Constant * CodeGenFunction::GenerateCovariantThunk(llvm::Function *Fn, GlobalDecl GD, bool Extern, const CovariantThunkAdjustment &Adjustment) { const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl()); const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>(); QualType ResultType = FPT->getResultType(); FunctionArgList Args; ImplicitParamDecl *ThisDecl = ImplicitParamDecl::Create(getContext(), 0, SourceLocation(), 0, MD->getThisType(getContext())); Args.push_back(std::make_pair(ThisDecl, ThisDecl->getType())); for (FunctionDecl::param_const_iterator i = MD->param_begin(), e = MD->param_end(); i != e; ++i) { ParmVarDecl *D = *i; Args.push_back(std::make_pair(D, D->getType())); } IdentifierInfo *II = &CGM.getContext().Idents.get("__thunk_named_foo_"); FunctionDecl *FD = FunctionDecl::Create(getContext(), getContext().getTranslationUnitDecl(), SourceLocation(), II, ResultType, 0, Extern ? FunctionDecl::Extern : FunctionDecl::Static, false, true); StartFunction(FD, ResultType, Fn, Args, SourceLocation()); // generate body const llvm::Type *Ty = CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(MD), FPT->isVariadic()); llvm::Value *Callee = CGM.GetAddrOfFunction(GD, Ty); CallArgList CallArgs; bool ShouldAdjustReturnPointer = true; QualType ArgType = MD->getThisType(getContext()); llvm::Value *Arg = Builder.CreateLoad(LocalDeclMap[ThisDecl], "this"); if (!Adjustment.ThisAdjustment.isEmpty()) { // Do the this adjustment. const llvm::Type *OrigTy = Callee->getType(); Arg = DynamicTypeAdjust(Arg, Adjustment.ThisAdjustment); if (!Adjustment.ReturnAdjustment.isEmpty()) { const CovariantThunkAdjustment &ReturnAdjustment = CovariantThunkAdjustment(ThunkAdjustment(), Adjustment.ReturnAdjustment); Callee = CGM.BuildCovariantThunk(GD, Extern, ReturnAdjustment); Callee = Builder.CreateBitCast(Callee, OrigTy); ShouldAdjustReturnPointer = false; } } CallArgs.push_back(std::make_pair(RValue::get(Arg), ArgType)); for (FunctionDecl::param_const_iterator i = MD->param_begin(), e = MD->param_end(); i != e; ++i) { ParmVarDecl *D = *i; QualType ArgType = D->getType(); // llvm::Value *Arg = CGF.GetAddrOfLocalVar(Dst); Expr *Arg = new (getContext()) DeclRefExpr(D, ArgType.getNonReferenceType(), SourceLocation()); CallArgs.push_back(std::make_pair(EmitCallArg(Arg, ArgType), ArgType)); } RValue RV = EmitCall(CGM.getTypes().getFunctionInfo(ResultType, CallArgs, FPT->getCallConv(), FPT->getNoReturnAttr()), Callee, ReturnValueSlot(), CallArgs, MD); if (ShouldAdjustReturnPointer && !Adjustment.ReturnAdjustment.isEmpty()) { bool CanBeZero = !(ResultType->isReferenceType() // FIXME: attr nonnull can't be zero either /* || ResultType->hasAttr<NonNullAttr>() */ ); // Do the return result adjustment. if (CanBeZero) { llvm::BasicBlock *NonZeroBlock = createBasicBlock(); llvm::BasicBlock *ZeroBlock = createBasicBlock(); llvm::BasicBlock *ContBlock = createBasicBlock(); const llvm::Type *Ty = RV.getScalarVal()->getType(); llvm::Value *Zero = llvm::Constant::getNullValue(Ty); Builder.CreateCondBr(Builder.CreateICmpNE(RV.getScalarVal(), Zero), NonZeroBlock, ZeroBlock); EmitBlock(NonZeroBlock); llvm::Value *NZ = DynamicTypeAdjust(RV.getScalarVal(), Adjustment.ReturnAdjustment); EmitBranch(ContBlock); EmitBlock(ZeroBlock); llvm::Value *Z = RV.getScalarVal(); EmitBlock(ContBlock); llvm::PHINode *RVOrZero = Builder.CreatePHI(Ty); RVOrZero->reserveOperandSpace(2); RVOrZero->addIncoming(NZ, NonZeroBlock); RVOrZero->addIncoming(Z, ZeroBlock); RV = RValue::get(RVOrZero); } else RV = RValue::get(DynamicTypeAdjust(RV.getScalarVal(), Adjustment.ReturnAdjustment)); } if (!ResultType->isVoidType()) EmitReturnOfRValue(RV, ResultType); FinishFunction(); return Fn; }
void DeclContextPrinter::PrintDeclContext(const DeclContext* DC, unsigned Indentation) { // Print DeclContext name. switch (DC->getDeclKind()) { case Decl::TranslationUnit: Out << "[translation unit] " << DC; break; case Decl::Namespace: { Out << "[namespace] "; const NamespaceDecl* ND = cast<NamespaceDecl>(DC); Out << ND->getNameAsString(); break; } case Decl::Enum: { const EnumDecl* ED = cast<EnumDecl>(DC); if (ED->isDefinition()) Out << "[enum] "; else Out << "<enum> "; Out << ED->getNameAsString(); break; } case Decl::Record: { const RecordDecl* RD = cast<RecordDecl>(DC); if (RD->isDefinition()) Out << "[struct] "; else Out << "<struct> "; Out << RD->getNameAsString(); break; } case Decl::CXXRecord: { const CXXRecordDecl* RD = cast<CXXRecordDecl>(DC); if (RD->isDefinition()) Out << "[class] "; else Out << "<class> "; Out << RD->getNameAsString() << " " << DC; break; } case Decl::ObjCMethod: Out << "[objc method]"; break; case Decl::ObjCInterface: Out << "[objc interface]"; break; case Decl::ObjCCategory: Out << "[objc category]"; break; case Decl::ObjCProtocol: Out << "[objc protocol]"; break; case Decl::ObjCImplementation: Out << "[objc implementation]"; break; case Decl::ObjCCategoryImpl: Out << "[objc categoryimpl]"; break; case Decl::LinkageSpec: Out << "[linkage spec]"; break; case Decl::Block: Out << "[block]"; break; case Decl::Function: { const FunctionDecl* FD = cast<FunctionDecl>(DC); if (FD->isThisDeclarationADefinition()) Out << "[function] "; else Out << "<function> "; Out << FD->getNameAsString(); // Print the parameters. Out << "("; bool PrintComma = false; for (FunctionDecl::param_const_iterator I = FD->param_begin(), E = FD->param_end(); I != E; ++I) { if (PrintComma) Out << ", "; else PrintComma = true; Out << (*I)->getNameAsString(); } Out << ")"; break; } case Decl::CXXMethod: { const CXXMethodDecl* D = cast<CXXMethodDecl>(DC); if (D->isOutOfLineDefinition()) Out << "[c++ method] "; else if (D->isImplicit()) Out << "(c++ method) "; else Out << "<c++ method> "; Out << D->getNameAsString(); // Print the parameters. Out << "("; bool PrintComma = false; for (FunctionDecl::param_const_iterator I = D->param_begin(), E = D->param_end(); I != E; ++I) { if (PrintComma) Out << ", "; else PrintComma = true; Out << (*I)->getNameAsString(); } Out << ")"; // Check the semantic DeclContext. const DeclContext* SemaDC = D->getDeclContext(); const DeclContext* LexicalDC = D->getLexicalDeclContext(); if (SemaDC != LexicalDC) Out << " [[" << SemaDC << "]]"; break; } case Decl::CXXConstructor: { const CXXConstructorDecl* D = cast<CXXConstructorDecl>(DC); if (D->isOutOfLineDefinition()) Out << "[c++ ctor] "; else if (D->isImplicit()) Out << "(c++ ctor) "; else Out << "<c++ ctor> "; Out << D->getNameAsString(); // Print the parameters. Out << "("; bool PrintComma = false; for (FunctionDecl::param_const_iterator I = D->param_begin(), E = D->param_end(); I != E; ++I) { if (PrintComma) Out << ", "; else PrintComma = true; Out << (*I)->getNameAsString(); } Out << ")"; // Check the semantic DC. const DeclContext* SemaDC = D->getDeclContext(); const DeclContext* LexicalDC = D->getLexicalDeclContext(); if (SemaDC != LexicalDC) Out << " [[" << SemaDC << "]]"; break; } case Decl::CXXDestructor: { const CXXDestructorDecl* D = cast<CXXDestructorDecl>(DC); if (D->isOutOfLineDefinition()) Out << "[c++ dtor] "; else if (D->isImplicit()) Out << "(c++ dtor) "; else Out << "<c++ dtor> "; Out << D->getNameAsString(); // Check the semantic DC. const DeclContext* SemaDC = D->getDeclContext(); const DeclContext* LexicalDC = D->getLexicalDeclContext(); if (SemaDC != LexicalDC) Out << " [[" << SemaDC << "]]"; break; } case Decl::CXXConversion: { const CXXConversionDecl* D = cast<CXXConversionDecl>(DC); if (D->isOutOfLineDefinition()) Out << "[c++ conversion] "; else if (D->isImplicit()) Out << "(c++ conversion) "; else Out << "<c++ conversion> "; Out << D->getNameAsString(); // Check the semantic DC. const DeclContext* SemaDC = D->getDeclContext(); const DeclContext* LexicalDC = D->getLexicalDeclContext(); if (SemaDC != LexicalDC) Out << " [[" << SemaDC << "]]"; break; } default: assert(0 && "a decl that inherits DeclContext isn't handled"); } Out << "\n"; // Print decls in the DeclContext. // FIXME: Should not use a NULL DeclContext! ASTContext *Context = 0; for (DeclContext::decl_iterator I = DC->decls_begin(*Context), E = DC->decls_end(*Context); I != E; ++I) { for (unsigned i = 0; i < Indentation; ++i) Out << " "; Decl::Kind DK = I->getKind(); switch (DK) { case Decl::Namespace: case Decl::Enum: case Decl::Record: case Decl::CXXRecord: case Decl::ObjCMethod: case Decl::ObjCInterface: case Decl::ObjCCategory: case Decl::ObjCProtocol: case Decl::ObjCImplementation: case Decl::ObjCCategoryImpl: case Decl::LinkageSpec: case Decl::Block: case Decl::Function: case Decl::CXXMethod: case Decl::CXXConstructor: case Decl::CXXDestructor: case Decl::CXXConversion: { DeclContext* DC = cast<DeclContext>(*I); PrintDeclContext(DC, Indentation+2); break; } case Decl::Field: { FieldDecl* FD = cast<FieldDecl>(*I); Out << "<field> " << FD->getNameAsString() << "\n"; break; } case Decl::Typedef: { TypedefDecl* TD = cast<TypedefDecl>(*I); Out << "<typedef> " << TD->getNameAsString() << "\n"; break; } case Decl::EnumConstant: { EnumConstantDecl* ECD = cast<EnumConstantDecl>(*I); Out << "<enum constant> " << ECD->getNameAsString() << "\n"; break; } case Decl::Var: { VarDecl* VD = cast<VarDecl>(*I); Out << "<var> " << VD->getNameAsString() << "\n"; break; } case Decl::ImplicitParam: { ImplicitParamDecl* IPD = cast<ImplicitParamDecl>(*I); Out << "<implicit parameter> " << IPD->getNameAsString() << "\n"; break; } case Decl::ParmVar: { ParmVarDecl* PVD = cast<ParmVarDecl>(*I); Out << "<parameter> " << PVD->getNameAsString() << "\n"; break; } case Decl::OriginalParmVar: { OriginalParmVarDecl* OPVD = cast<OriginalParmVarDecl>(*I); Out << "<original parameter> " << OPVD->getNameAsString() << "\n"; break; } case Decl::ObjCProperty: { ObjCPropertyDecl* OPD = cast<ObjCPropertyDecl>(*I); Out << "<objc property> " << OPD->getNameAsString() << "\n"; break; } default: fprintf(stderr, "DeclKind: %d \"%s\"\n", DK, I->getDeclKindName()); assert(0 && "decl unhandled"); } } }