/// \brief Add a lambda's conversion to block pointer. static void addBlockPointerConversion(Sema &S, SourceRange IntroducerRange, CXXRecordDecl *Class, CXXMethodDecl *CallOperator) { const FunctionProtoType *Proto = CallOperator->getType()->getAs<FunctionProtoType>(); QualType BlockPtrTy; { FunctionProtoType::ExtProtoInfo ExtInfo = Proto->getExtProtoInfo(); ExtInfo.TypeQuals = 0; QualType FunctionTy = S.Context.getFunctionType(Proto->getResultType(), ArrayRef<QualType>(Proto->arg_type_begin(), Proto->getNumArgs()), ExtInfo); BlockPtrTy = S.Context.getBlockPointerType(FunctionTy); } FunctionProtoType::ExtProtoInfo ExtInfo; ExtInfo.TypeQuals = Qualifiers::Const; QualType ConvTy = S.Context.getFunctionType(BlockPtrTy, ArrayRef<QualType>(), ExtInfo); SourceLocation Loc = IntroducerRange.getBegin(); DeclarationName Name = S.Context.DeclarationNames.getCXXConversionFunctionName( S.Context.getCanonicalType(BlockPtrTy)); DeclarationNameLoc NameLoc; NameLoc.NamedType.TInfo = S.Context.getTrivialTypeSourceInfo(BlockPtrTy, Loc); CXXConversionDecl *Conversion = CXXConversionDecl::Create(S.Context, Class, Loc, DeclarationNameInfo(Name, Loc, NameLoc), ConvTy, S.Context.getTrivialTypeSourceInfo(ConvTy, Loc), /*isInline=*/false, /*isExplicit=*/false, /*isConstexpr=*/false, CallOperator->getBody()->getLocEnd()); Conversion->setAccess(AS_public); Conversion->setImplicit(true); Class->addDecl(Conversion); }
/// \brief Add a lambda's conversion to function pointer, as described in /// C++11 [expr.prim.lambda]p6. static void addFunctionPointerConversion(Sema &S, SourceRange IntroducerRange, CXXRecordDecl *Class, CXXMethodDecl *CallOperator) { // Add the conversion to function pointer. const FunctionProtoType *Proto = CallOperator->getType()->getAs<FunctionProtoType>(); QualType FunctionPtrTy; QualType FunctionTy; { FunctionProtoType::ExtProtoInfo ExtInfo = Proto->getExtProtoInfo(); ExtInfo.TypeQuals = 0; FunctionTy = S.Context.getFunctionType(Proto->getResultType(), Proto->arg_type_begin(), Proto->getNumArgs(), ExtInfo); FunctionPtrTy = S.Context.getPointerType(FunctionTy); } FunctionProtoType::ExtProtoInfo ExtInfo; ExtInfo.TypeQuals = Qualifiers::Const; QualType ConvTy = S.Context.getFunctionType(FunctionPtrTy, 0, 0, ExtInfo); SourceLocation Loc = IntroducerRange.getBegin(); DeclarationName Name = S.Context.DeclarationNames.getCXXConversionFunctionName( S.Context.getCanonicalType(FunctionPtrTy)); DeclarationNameLoc NameLoc; NameLoc.NamedType.TInfo = S.Context.getTrivialTypeSourceInfo(FunctionPtrTy, Loc); CXXConversionDecl *Conversion = CXXConversionDecl::Create(S.Context, Class, Loc, DeclarationNameInfo(Name, Loc, NameLoc), ConvTy, S.Context.getTrivialTypeSourceInfo(ConvTy, Loc), /*isInline=*/false, /*isExplicit=*/false, /*isConstexpr=*/false, CallOperator->getBody()->getLocEnd()); Conversion->setAccess(AS_public); Conversion->setImplicit(true); Class->addDecl(Conversion); // Add a non-static member function "__invoke" that will be the result of // the conversion. Name = &S.Context.Idents.get("__invoke"); CXXMethodDecl *Invoke = CXXMethodDecl::Create(S.Context, Class, Loc, DeclarationNameInfo(Name, Loc), FunctionTy, CallOperator->getTypeSourceInfo(), /*IsStatic=*/true, SC_Static, /*IsInline=*/true, /*IsConstexpr=*/false, CallOperator->getBody()->getLocEnd()); SmallVector<ParmVarDecl *, 4> InvokeParams; for (unsigned I = 0, N = CallOperator->getNumParams(); I != N; ++I) { ParmVarDecl *From = CallOperator->getParamDecl(I); InvokeParams.push_back(ParmVarDecl::Create(S.Context, Invoke, From->getLocStart(), From->getLocation(), From->getIdentifier(), From->getType(), From->getTypeSourceInfo(), From->getStorageClass(), From->getStorageClassAsWritten(), /*DefaultArg=*/0)); } Invoke->setParams(InvokeParams); Invoke->setAccess(AS_private); Invoke->setImplicit(true); Class->addDecl(Invoke); }
void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) { if (!D->getDescribedFunctionTemplate() && !D->isFunctionTemplateSpecialization()) prettyPrintPragmas(D); if (D->isFunctionTemplateSpecialization()) Out << "template<> "; CXXConstructorDecl *CDecl = dyn_cast<CXXConstructorDecl>(D); CXXConversionDecl *ConversionDecl = dyn_cast<CXXConversionDecl>(D); if (!Policy.SuppressSpecifiers) { switch (D->getStorageClass()) { case SC_None: break; case SC_Extern: Out << "extern "; break; case SC_Static: Out << "static "; break; case SC_PrivateExtern: Out << "__private_extern__ "; break; case SC_Auto: case SC_Register: llvm_unreachable("invalid for functions"); } if (D->isInlineSpecified()) Out << "inline "; if (D->isVirtualAsWritten()) Out << "virtual "; if (D->isModulePrivate()) Out << "__module_private__ "; if (D->isConstexpr() && !D->isExplicitlyDefaulted()) Out << "constexpr "; if ((CDecl && CDecl->isExplicitSpecified()) || (ConversionDecl && ConversionDecl->isExplicit())) Out << "explicit "; } PrintingPolicy SubPolicy(Policy); SubPolicy.SuppressSpecifiers = false; std::string Proto = D->getNameInfo().getAsString(); if (const TemplateArgumentList *TArgs = D->getTemplateSpecializationArgs()) { llvm::raw_string_ostream POut(Proto); DeclPrinter TArgPrinter(POut, SubPolicy, Indentation); TArgPrinter.printTemplateArguments(*TArgs); } QualType Ty = D->getType(); while (const ParenType *PT = dyn_cast<ParenType>(Ty)) { Proto = '(' + Proto + ')'; Ty = PT->getInnerType(); } prettyPrintAttributes(D); if (const FunctionType *AFT = Ty->getAs<FunctionType>()) { const FunctionProtoType *FT = nullptr; if (D->hasWrittenPrototype()) FT = dyn_cast<FunctionProtoType>(AFT); Proto += "("; if (FT) { llvm::raw_string_ostream POut(Proto); DeclPrinter ParamPrinter(POut, SubPolicy, Indentation); for (unsigned i = 0, e = D->getNumParams(); i != e; ++i) { if (i) POut << ", "; ParamPrinter.VisitParmVarDecl(D->getParamDecl(i)); } if (FT->isVariadic()) { if (D->getNumParams()) POut << ", "; POut << "..."; } } else if (D->doesThisDeclarationHaveABody() && !D->hasPrototype()) { for (unsigned i = 0, e = D->getNumParams(); i != e; ++i) { if (i) Proto += ", "; Proto += D->getParamDecl(i)->getNameAsString(); } } Proto += ")"; if (FT) { if (FT->isConst()) Proto += " const"; if (FT->isVolatile()) Proto += " volatile"; if (FT->isRestrict()) Proto += " restrict"; switch (FT->getRefQualifier()) { case RQ_None: break; case RQ_LValue: Proto += " &"; break; case RQ_RValue: Proto += " &&"; break; } } if (FT && FT->hasDynamicExceptionSpec()) { Proto += " throw("; if (FT->getExceptionSpecType() == EST_MSAny) Proto += "..."; else for (unsigned I = 0, N = FT->getNumExceptions(); I != N; ++I) { if (I) Proto += ", "; Proto += FT->getExceptionType(I).getAsString(SubPolicy); } Proto += ")"; } else if (FT && isNoexceptExceptionSpec(FT->getExceptionSpecType())) { Proto += " noexcept"; if (FT->getExceptionSpecType() == EST_ComputedNoexcept) { Proto += "("; llvm::raw_string_ostream EOut(Proto); FT->getNoexceptExpr()->printPretty(EOut, nullptr, SubPolicy, Indentation); EOut.flush(); Proto += EOut.str(); Proto += ")"; } } if (CDecl) { bool HasInitializerList = false; for (const auto *BMInitializer : CDecl->inits()) { if (BMInitializer->isInClassMemberInitializer()) continue; if (!HasInitializerList) { Proto += " : "; Out << Proto; Proto.clear(); HasInitializerList = true; } else Out << ", "; if (BMInitializer->isAnyMemberInitializer()) { FieldDecl *FD = BMInitializer->getAnyMember(); Out << *FD; } else { Out << QualType(BMInitializer->getBaseClass(), 0).getAsString(Policy); } Out << "("; if (!BMInitializer->getInit()) { // Nothing to print } else { Expr *Init = BMInitializer->getInit(); if (ExprWithCleanups *Tmp = dyn_cast<ExprWithCleanups>(Init)) Init = Tmp->getSubExpr(); Init = Init->IgnoreParens(); Expr *SimpleInit = nullptr; Expr **Args = nullptr; unsigned NumArgs = 0; if (ParenListExpr *ParenList = dyn_cast<ParenListExpr>(Init)) { Args = ParenList->getExprs(); NumArgs = ParenList->getNumExprs(); } else if (CXXConstructExpr *Construct = dyn_cast<CXXConstructExpr>(Init)) { Args = Construct->getArgs(); NumArgs = Construct->getNumArgs(); } else SimpleInit = Init; if (SimpleInit) SimpleInit->printPretty(Out, nullptr, Policy, Indentation); else { for (unsigned I = 0; I != NumArgs; ++I) { assert(Args[I] != nullptr && "Expected non-null Expr"); if (isa<CXXDefaultArgExpr>(Args[I])) break; if (I) Out << ", "; Args[I]->printPretty(Out, nullptr, Policy, Indentation); } } } Out << ")"; if (BMInitializer->isPackExpansion()) Out << "..."; } } else if (!ConversionDecl && !isa<CXXDestructorDecl>(D)) { if (FT && FT->hasTrailingReturn()) { Out << "auto " << Proto << " -> "; Proto.clear(); } AFT->getReturnType().print(Out, Policy, Proto); Proto.clear(); } Out << Proto; } else { Ty.print(Out, Policy, Proto); } if (D->isPure()) Out << " = 0"; else if (D->isDeletedAsWritten()) Out << " = delete"; else if (D->isExplicitlyDefaulted()) Out << " = default"; else if (D->doesThisDeclarationHaveABody()) { if (!Policy.TerseOutput) { if (!D->hasPrototype() && D->getNumParams()) { // This is a K&R function definition, so we need to print the // parameters. Out << '\n'; DeclPrinter ParamPrinter(Out, SubPolicy, Indentation); Indentation += Policy.Indentation; for (unsigned i = 0, e = D->getNumParams(); i != e; ++i) { Indent(); ParamPrinter.VisitParmVarDecl(D->getParamDecl(i)); Out << ";\n"; } Indentation -= Policy.Indentation; } else Out << ' '; if (D->getBody()) D->getBody()->printPretty(Out, nullptr, SubPolicy, Indentation); } else { if (isa<CXXConstructorDecl>(*D)) Out << " {}"; } } }