#include "clang/Sema/DeclSpec.h"
#include "clang/Sema/Initialization.h"
#include "clang/Sema/Lookup.h"
#include "clang/Sema/Scope.h"
#include "clang/Sema/ScopeInfo.h"
#include "clang/Sema/SemaInternal.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/AST/ExprCXX.h"
using namespace clang;
using namespace sema;
CXXRecordDecl *Sema::createLambdaClosureType(SourceRange IntroducerRange,
TypeSourceInfo *Info,
bool KnownDependent) {
DeclContext *DC = CurContext;
while (!(DC->isFunctionOrMethod() || DC->isRecord() || DC->isFileContext()))
DC = DC->getParent();
CXXRecordDecl *Class = CXXRecordDecl::CreateLambda(Context, DC, Info,
IntroducerRange.getBegin(),
KnownDependent);
DC->addDecl(Class);
return Class;
}
static bool isInInlineFunction(const DeclContext *DC) {
while (!DC->isFileContext()) {
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(DC))
if (FD->isInlined())
return true;
DC = DC->getLexicalParent();
}
return false;
}
CXXMethodDecl *Sema::startLambdaDefinition(CXXRecordDecl *Class,
SourceRange IntroducerRange,
TypeSourceInfo *MethodType,
SourceLocation EndLoc,
llvm::ArrayRef<ParmVarDecl *> Params) {
DeclarationName MethodName
= Context.DeclarationNames.getCXXOperatorName(OO_Call);
DeclarationNameLoc MethodNameLoc;
MethodNameLoc.CXXOperatorName.BeginOpNameLoc
= IntroducerRange.getBegin().getRawEncoding();
MethodNameLoc.CXXOperatorName.EndOpNameLoc
= IntroducerRange.getEnd().getRawEncoding();
CXXMethodDecl *Method
= CXXMethodDecl::Create(Context, Class, EndLoc,
DeclarationNameInfo(MethodName,
IntroducerRange.getBegin(),
MethodNameLoc),
MethodType->getType(), MethodType,
false,
SC_None,
true,
false,
EndLoc);
Method->setAccess(AS_public);
Method->setLexicalDeclContext(CurContext);
if (!Params.empty()) {
Method->setParams(Params);
CheckParmsForFunctionDef(const_cast<ParmVarDecl **>(Params.begin()),
const_cast<ParmVarDecl **>(Params.end()),
false);
for (CXXMethodDecl::param_iterator P = Method->param_begin(),
PEnd = Method->param_end();
P != PEnd; ++P)
(*P)->setOwningFunction(Method);
}
Decl *ContextDecl = ExprEvalContexts.back().LambdaContextDecl;
enum ContextKind {
Normal,
DefaultArgument,
DataMember,
StaticDataMember
} Kind = Normal;
if (ContextDecl) {
if (ParmVarDecl *Param = dyn_cast<ParmVarDecl>(ContextDecl)) {
if (const DeclContext *LexicalDC
= Param->getDeclContext()->getLexicalParent())
if (LexicalDC->isRecord())
Kind = DefaultArgument;
} else if (VarDecl *Var = dyn_cast<VarDecl>(ContextDecl)) {
if (Var->getDeclContext()->isRecord())
Kind = StaticDataMember;
} else if (isa<FieldDecl>(ContextDecl)) {
Kind = DataMember;
}
}
bool IsInNonspecializedTemplate =
!ActiveTemplateInstantiations.empty() || CurContext->isDependentContext();
unsigned ManglingNumber;
switch (Kind) {
case Normal:
if ((IsInNonspecializedTemplate &&
!(ContextDecl && isa<ParmVarDecl>(ContextDecl))) ||
isInInlineFunction(CurContext))
ManglingNumber = Context.getLambdaManglingNumber(Method);
else
ManglingNumber = 0;
ContextDecl = 0;
break;
case StaticDataMember:
if (!IsInNonspecializedTemplate) {
ManglingNumber = 0;
ContextDecl = 0;
break;
}
case DataMember:
case DefaultArgument:
ManglingNumber = ExprEvalContexts.back().getLambdaMangleContext()
.getManglingNumber(Method);
break;
}
Class->setLambdaMangling(ManglingNumber, ContextDecl);
return Method;
}
LambdaScopeInfo *Sema::enterLambdaScope(CXXMethodDecl *CallOperator,
SourceRange IntroducerRange,
LambdaCaptureDefault CaptureDefault,
bool ExplicitParams,
bool ExplicitResultType,
bool Mutable) {
PushLambdaScope(CallOperator->getParent(), CallOperator);
LambdaScopeInfo *LSI = getCurLambda();
if (CaptureDefault == LCD_ByCopy)
LSI->ImpCaptureStyle = LambdaScopeInfo::ImpCap_LambdaByval;
else if (CaptureDefault == LCD_ByRef)
LSI->ImpCaptureStyle = LambdaScopeInfo::ImpCap_LambdaByref;
LSI->IntroducerRange = IntroducerRange;
LSI->ExplicitParams = ExplicitParams;
LSI->Mutable = Mutable;
if (ExplicitResultType) {
LSI->ReturnType = CallOperator->getResultType();
if (!LSI->ReturnType->isDependentType() &&
!LSI->ReturnType->isVoidType()) {
if (RequireCompleteType(CallOperator->getLocStart(), LSI->ReturnType,
diag::err_lambda_incomplete_result)) {
} else if (LSI->ReturnType->isObjCObjectOrInterfaceType()) {
Diag(CallOperator->getLocStart(), diag::err_lambda_objc_object_result)
<< LSI->ReturnType;
}
}
} else {
LSI->HasImplicitReturnType = true;
}
return LSI;
}
void Sema::finishLambdaExplicitCaptures(LambdaScopeInfo *LSI) {
LSI->finishedExplicitCaptures();
}
void Sema::addLambdaParameters(CXXMethodDecl *CallOperator, Scope *CurScope) {
for (unsigned p = 0, NumParams = CallOperator->getNumParams();
p < NumParams; ++p) {
ParmVarDecl *Param = CallOperator->getParamDecl(p);
if (CurScope && Param->getIdentifier()) {
CheckShadow(CurScope, Param);
PushOnScopeChains(Param, CurScope);
}
}
}
static bool checkReturnValueType(const ASTContext &Ctx, const Expr *E,
QualType &DeducedType,
QualType &AlternateType) {
if (!E) {
if (AlternateType.isNull())
AlternateType = Ctx.VoidTy;
return Ctx.hasSameType(DeducedType, Ctx.VoidTy);
}
QualType StrictType = E->getType();
QualType LooseType = StrictType;
if (!Ctx.getLangOpts().CPlusPlus) {
const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E->IgnoreParenImpCasts());
if (DRE) {
const Decl *D = DRE->getDecl();
if (const EnumConstantDecl *ECD = dyn_cast<EnumConstantDecl>(D)) {
const EnumDecl *Enum = cast<EnumDecl>(ECD->getDeclContext());
if (Enum->getDeclName() || Enum->getTypedefNameForAnonDecl())
LooseType = Ctx.getTypeDeclType(Enum);
}
}
}
if (AlternateType.isNull())
AlternateType = LooseType;
if (Ctx.hasSameType(DeducedType, StrictType)) {
if (AlternateType != Ctx.DependentTy)
if (!Ctx.hasSameType(AlternateType, LooseType))
AlternateType = Ctx.VoidTy;
return true;
}
if (Ctx.hasSameType(DeducedType, LooseType)) {
AlternateType = Ctx.DependentTy;
return true;
}
if (Ctx.hasSameType(AlternateType, StrictType) ||
Ctx.hasSameType(AlternateType, LooseType)) {
DeducedType = AlternateType;
AlternateType = Ctx.DependentTy;
return true;
}
return false;
}
void Sema::deduceClosureReturnType(CapturingScopeInfo &CSI) {
assert(CSI.HasImplicitReturnType);
ASTContext &Ctx = getASTContext();
if (CSI.Returns.empty()) {
if (CSI.ReturnType.isNull())
CSI.ReturnType = Ctx.VoidTy;
return;
}
assert(!CSI.ReturnType.isNull() && "We should have a tentative return type.");
if (CSI.ReturnType->isDependentType())
return;
SmallVectorImpl<ReturnStmt*>::iterator I = CSI.Returns.begin(),
E = CSI.Returns.end();
if (I+1 == E)
return;
QualType AlternateType;
for (; I != E; ++I) {
const ReturnStmt *RS = *I;
const Expr *RetE = RS->getRetValue();
if (!checkReturnValueType(Ctx, RetE, CSI.ReturnType, AlternateType)) {
Diag(RS->getLocStart(),
diag::err_typecheck_missing_return_type_incompatible)
<< (RetE ? RetE->getType() : Ctx.VoidTy) << CSI.ReturnType
<< isa<LambdaScopeInfo>(CSI);
AlternateType = Ctx.VoidTy;
}
}
if (AlternateType == Ctx.DependentTy) {
for (SmallVectorImpl<ReturnStmt*>::iterator I = CSI.Returns.begin(),
E = CSI.Returns.end();
I != E; ++I) {
ReturnStmt *RS = *I;
Expr *RetE = RS->getRetValue();
if (RetE->getType() == CSI.ReturnType)
continue;
assert(CSI.ReturnType->isIntegralOrUnscopedEnumerationType());
assert(RetE->getType()->isIntegralOrUnscopedEnumerationType());
ExprResult Casted = ImpCastExprToType(RetE, CSI.ReturnType,
CK_IntegralCast);
assert(Casted.isUsable());
RS->setRetValue(Casted.take());
}
}
}
void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
Declarator &ParamInfo,
Scope *CurScope) {
bool KnownDependent = false;
if (Scope *TmplScope = CurScope->getTemplateParamParent())
if (!TmplScope->decl_empty())
KnownDependent = true;
TypeSourceInfo *MethodTyInfo;
bool ExplicitParams = true;
bool ExplicitResultType = true;
bool ContainsUnexpandedParameterPack = false;
SourceLocation EndLoc;
llvm::SmallVector<ParmVarDecl *, 8> Params;
if (ParamInfo.getNumTypeObjects() == 0) {
FunctionProtoType::ExtProtoInfo EPI;
EPI.HasTrailingReturn = true;
EPI.TypeQuals |= DeclSpec::TQ_const;
QualType MethodTy = Context.getFunctionType(Context.DependentTy,
0, 0, EPI);
MethodTyInfo = Context.getTrivialTypeSourceInfo(MethodTy);
ExplicitParams = false;
ExplicitResultType = false;
EndLoc = Intro.Range.getEnd();
} else {
assert(ParamInfo.isFunctionDeclarator() &&
"lambda-declarator is a function");
DeclaratorChunk::FunctionTypeInfo &FTI = ParamInfo.getFunctionTypeInfo();
if (!FTI.hasMutableQualifier())
FTI.TypeQuals |= DeclSpec::TQ_const;
MethodTyInfo = GetTypeForDeclarator(ParamInfo, CurScope);
assert(MethodTyInfo && "no type from lambda-declarator");
EndLoc = ParamInfo.getSourceRange().getEnd();
ExplicitResultType
= MethodTyInfo->getType()->getAs<FunctionType>()->getResultType()
!= Context.DependentTy;
if (FTI.NumArgs == 1 && !FTI.isVariadic && FTI.ArgInfo[0].Ident == 0 &&
cast<ParmVarDecl>(FTI.ArgInfo[0].Param)->getType()->isVoidType()) {
checkVoidParamDecl(cast<ParmVarDecl>(FTI.ArgInfo[0].Param));
} else {
Params.reserve(FTI.NumArgs);
for (unsigned i = 0, e = FTI.NumArgs; i != e; ++i)
Params.push_back(cast<ParmVarDecl>(FTI.ArgInfo[i].Param));
}
if (MethodTyInfo->getType()->containsUnexpandedParameterPack())
ContainsUnexpandedParameterPack = true;
}
CXXRecordDecl *Class = createLambdaClosureType(Intro.Range, MethodTyInfo,
KnownDependent);
CXXMethodDecl *Method = startLambdaDefinition(Class, Intro.Range,
MethodTyInfo, EndLoc, Params);
if (ExplicitParams)
CheckCXXDefaultArguments(Method);
ProcessDeclAttributes(CurScope, Method, ParamInfo);
PushDeclContext(CurScope, Method);
LambdaScopeInfo *LSI
= enterLambdaScope(Method, Intro.Range, Intro.Default, ExplicitParams,
ExplicitResultType,
!Method->isConst());
SourceLocation PrevCaptureLoc
= Intro.Default == LCD_None? Intro.Range.getBegin() : Intro.DefaultLoc;
for (llvm::SmallVector<LambdaCapture, 4>::const_iterator
C = Intro.Captures.begin(),
E = Intro.Captures.end();
C != E;
PrevCaptureLoc = C->Loc, ++C) {
if (C->Kind == LCK_This) {
if (LSI->isCXXThisCaptured()) {
Diag(C->Loc, diag::err_capture_more_than_once)
<< "'this'"
<< SourceRange(LSI->getCXXThisCapture().getLocation())
<< FixItHint::CreateRemoval(
SourceRange(PP.getLocForEndOfToken(PrevCaptureLoc), C->Loc));
continue;
}
if (Intro.Default == LCD_ByCopy) {
Diag(C->Loc, diag::err_this_capture_with_copy_default)
<< FixItHint::CreateRemoval(
SourceRange(PP.getLocForEndOfToken(PrevCaptureLoc), C->Loc));
continue;
}
QualType ThisCaptureType = getCurrentThisType();
if (ThisCaptureType.isNull()) {
Diag(C->Loc, diag::err_this_capture) << true;
continue;
}
CheckCXXThisCapture(C->Loc, true);
continue;
}
assert(C->Id && "missing identifier for capture");
if (C->Kind == LCK_ByRef && Intro.Default == LCD_ByRef) {
Diag(C->Loc, diag::err_reference_capture_with_reference_default)
<< FixItHint::CreateRemoval(
SourceRange(PP.getLocForEndOfToken(PrevCaptureLoc), C->Loc));
continue;
} else if (C->Kind == LCK_ByCopy && Intro.Default == LCD_ByCopy) {
Diag(C->Loc, diag::err_copy_capture_with_copy_default)
<< FixItHint::CreateRemoval(
SourceRange(PP.getLocForEndOfToken(PrevCaptureLoc), C->Loc));
continue;
}
DeclarationNameInfo Name(C->Id, C->Loc);
LookupResult R(*this, Name, LookupOrdinaryName);
LookupName(R, CurScope);
if (R.isAmbiguous())
continue;
if (R.empty()) {
CXXScopeSpec ScopeSpec;
DeclFilterCCC<VarDecl> Validator;
if (DiagnoseEmptyLookup(CurScope, ScopeSpec, R, Validator))
continue;
}
VarDecl *Var = R.getAsSingle<VarDecl>();
if (!Var) {
Diag(C->Loc, diag::err_capture_does_not_name_variable) << C->Id;
continue;
}
if (Var->isInvalidDecl())
continue;
if (!Var->hasLocalStorage()) {
Diag(C->Loc, diag::err_capture_non_automatic_variable) << C->Id;
Diag(Var->getLocation(), diag::note_previous_decl) << C->Id;
continue;
}
if (LSI->isCaptured(Var)) {
Diag(C->Loc, diag::err_capture_more_than_once)
<< C->Id
<< SourceRange(LSI->getCapture(Var).getLocation())
<< FixItHint::CreateRemoval(
SourceRange(PP.getLocForEndOfToken(PrevCaptureLoc), C->Loc));
continue;
}
SourceLocation EllipsisLoc;
if (C->EllipsisLoc.isValid()) {
if (Var->isParameterPack()) {
EllipsisLoc = C->EllipsisLoc;
} else {
Diag(C->EllipsisLoc, diag::err_pack_expansion_without_parameter_packs)
<< SourceRange(C->Loc);
}
} else if (Var->isParameterPack()) {
ContainsUnexpandedParameterPack = true;
}
TryCaptureKind Kind = C->Kind == LCK_ByRef ? TryCapture_ExplicitByRef :
TryCapture_ExplicitByVal;
tryCaptureVariable(Var, C->Loc, Kind, EllipsisLoc);
}
finishLambdaExplicitCaptures(LSI);
LSI->ContainsUnexpandedParameterPack = ContainsUnexpandedParameterPack;
addLambdaParameters(Method, CurScope);
PushExpressionEvaluationContext(PotentiallyEvaluated);
}
void Sema::ActOnLambdaError(SourceLocation StartLoc, Scope *CurScope,
bool IsInstantiation) {
DiscardCleanupsInEvaluationContext();
PopExpressionEvaluationContext();
if (!IsInstantiation)
PopDeclContext();
LambdaScopeInfo *LSI = getCurLambda();
CXXRecordDecl *Class = LSI->Lambda;
Class->setInvalidDecl();
SmallVector<Decl*, 4> Fields;
for (RecordDecl::field_iterator i = Class->field_begin(),
e = Class->field_end(); i != e; ++i)
Fields.push_back(*i);
ActOnFields(0, Class->getLocation(), Class, Fields,
SourceLocation(), SourceLocation(), 0);
CheckCompletedCXXClass(Class);
PopFunctionScopeInfo();
}
static void addFunctionPointerConversion(Sema &S,
SourceRange IntroducerRange,
CXXRecordDecl *Class,
CXXMethodDecl *CallOperator) {
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),
false, false,
false,
CallOperator->getBody()->getLocEnd());
Conversion->setAccess(AS_public);
Conversion->setImplicit(true);
Class->addDecl(Conversion);
Name = &S.Context.Idents.get("__invoke");
CXXMethodDecl *Invoke
= CXXMethodDecl::Create(S.Context, Class, Loc,
DeclarationNameInfo(Name, Loc), FunctionTy,
CallOperator->getTypeSourceInfo(),
true, SC_Static, true,
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(),
0));
}
Invoke->setParams(InvokeParams);
Invoke->setAccess(AS_private);
Invoke->setImplicit(true);
Class->addDecl(Invoke);
}
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(),
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, 0, 0, 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),
false, false,
false,
CallOperator->getBody()->getLocEnd());
Conversion->setAccess(AS_public);
Conversion->setImplicit(true);
Class->addDecl(Conversion);
}
ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body,
Scope *CurScope,
bool IsInstantiation) {
llvm::SmallVector<LambdaExpr::Capture, 4> Captures;
llvm::SmallVector<Expr *, 4> CaptureInits;
LambdaCaptureDefault CaptureDefault;
CXXRecordDecl *Class;
CXXMethodDecl *CallOperator;
SourceRange IntroducerRange;
bool ExplicitParams;
bool ExplicitResultType;
bool LambdaExprNeedsCleanups;
bool ContainsUnexpandedParameterPack;
llvm::SmallVector<VarDecl *, 4> ArrayIndexVars;
llvm::SmallVector<unsigned, 4> ArrayIndexStarts;
{
LambdaScopeInfo *LSI = getCurLambda();
CallOperator = LSI->CallOperator;
Class = LSI->Lambda;
IntroducerRange = LSI->IntroducerRange;
ExplicitParams = LSI->ExplicitParams;
ExplicitResultType = !LSI->HasImplicitReturnType;
LambdaExprNeedsCleanups = LSI->ExprNeedsCleanups;
ContainsUnexpandedParameterPack = LSI->ContainsUnexpandedParameterPack;
ArrayIndexVars.swap(LSI->ArrayIndexVars);
ArrayIndexStarts.swap(LSI->ArrayIndexStarts);
for (unsigned I = 0, N = LSI->Captures.size(); I != N; ++I) {
LambdaScopeInfo::Capture From = LSI->Captures[I];
assert(!From.isBlockCapture() && "Cannot capture __block variables");
bool IsImplicit = I >= LSI->NumExplicitCaptures;
if (From.isThisCapture()) {
Captures.push_back(LambdaExpr::Capture(From.getLocation(),
IsImplicit,
LCK_This));
CaptureInits.push_back(new (Context) CXXThisExpr(From.getLocation(),
getCurrentThisType(),
true));
continue;
}
VarDecl *Var = From.getVariable();
LambdaCaptureKind Kind = From.isCopyCapture()? LCK_ByCopy : LCK_ByRef;
Captures.push_back(LambdaExpr::Capture(From.getLocation(), IsImplicit,
Kind, Var, From.getEllipsisLoc()));
CaptureInits.push_back(From.getCopyExpr());
}
switch (LSI->ImpCaptureStyle) {
case CapturingScopeInfo::ImpCap_None:
CaptureDefault = LCD_None;
break;
case CapturingScopeInfo::ImpCap_LambdaByval:
CaptureDefault = LCD_ByCopy;
break;
case CapturingScopeInfo::ImpCap_LambdaByref:
CaptureDefault = LCD_ByRef;
break;
case CapturingScopeInfo::ImpCap_Block:
llvm_unreachable("block capture in lambda");
break;
}
if (LSI->HasImplicitReturnType) {
deduceClosureReturnType(*LSI);
if (LSI->ReturnType.isNull()) {
LSI->ReturnType = Context.VoidTy;
}
const FunctionProtoType *Proto
= CallOperator->getType()->getAs<FunctionProtoType>();
QualType FunctionTy
= Context.getFunctionType(LSI->ReturnType,
Proto->arg_type_begin(),
Proto->getNumArgs(),
Proto->getExtProtoInfo());
CallOperator->setType(FunctionTy);
}
ActOnFinishFunctionBody(CallOperator, Body, IsInstantiation);
CallOperator->setLexicalDeclContext(Class);
Class->addDecl(CallOperator);
PopExpressionEvaluationContext();
if (Captures.empty() && CaptureDefault == LCD_None)
addFunctionPointerConversion(*this, IntroducerRange, Class,
CallOperator);
if (getLangOpts().Blocks && getLangOpts().ObjC1)
addBlockPointerConversion(*this, IntroducerRange, Class, CallOperator);
SmallVector<Decl*, 4> Fields;
for (RecordDecl::field_iterator i = Class->field_begin(),
e = Class->field_end(); i != e; ++i)
Fields.push_back(*i);
ActOnFields(0, Class->getLocation(), Class, Fields,
SourceLocation(), SourceLocation(), 0);
CheckCompletedCXXClass(Class);
}
if (LambdaExprNeedsCleanups)
ExprNeedsCleanups = true;
LambdaExpr *Lambda = LambdaExpr::Create(Context, Class, IntroducerRange,
CaptureDefault, Captures,
ExplicitParams, ExplicitResultType,
CaptureInits, ArrayIndexVars,
ArrayIndexStarts, Body->getLocEnd(),
ContainsUnexpandedParameterPack);
if (!CurContext->isDependentContext()) {
switch (ExprEvalContexts.back().Context) {
case Unevaluated:
ExprEvalContexts.back().Lambdas.push_back(Lambda);
break;
case ConstantEvaluated:
case PotentiallyEvaluated:
case PotentiallyEvaluatedIfUsed:
break;
}
}
return MaybeBindToTemporary(Lambda);
}
ExprResult Sema::BuildBlockForLambdaConversion(SourceLocation CurrentLocation,
SourceLocation ConvLocation,
CXXConversionDecl *Conv,
Expr *Src) {
CXXRecordDecl *Lambda = Conv->getParent();
CXXMethodDecl *CallOperator
= cast<CXXMethodDecl>(
*Lambda->lookup(
Context.DeclarationNames.getCXXOperatorName(OO_Call)).first);
CallOperator->setReferenced();
CallOperator->setUsed();
ExprResult Init = PerformCopyInitialization(
InitializedEntity::InitializeBlock(ConvLocation,
Src->getType(),
false),
CurrentLocation, Src);
if (!Init.isInvalid())
Init = ActOnFinishFullExpr(Init.take());
if (Init.isInvalid())
return ExprError();
BlockDecl *Block = BlockDecl::Create(Context, CurContext, ConvLocation);
Block->setSignatureAsWritten(CallOperator->getTypeSourceInfo());
Block->setIsVariadic(CallOperator->isVariadic());
Block->setBlockMissingReturnType(false);
SmallVector<ParmVarDecl *, 4> BlockParams;
for (unsigned I = 0, N = CallOperator->getNumParams(); I != N; ++I) {
ParmVarDecl *From = CallOperator->getParamDecl(I);
BlockParams.push_back(ParmVarDecl::Create(Context, Block,
From->getLocStart(),
From->getLocation(),
From->getIdentifier(),
From->getType(),
From->getTypeSourceInfo(),
From->getStorageClass(),
From->getStorageClassAsWritten(),
0));
}
Block->setParams(BlockParams);
Block->setIsConversionFromLambda(true);
TypeSourceInfo *CapVarTSI =
Context.getTrivialTypeSourceInfo(Src->getType());
VarDecl *CapVar = VarDecl::Create(Context, Block, ConvLocation,
ConvLocation, 0,
Src->getType(), CapVarTSI,
SC_None, SC_None);
BlockDecl::Capture Capture(CapVar, false,
false, Init.take());
Block->setCaptures(Context, &Capture, &Capture + 1,
false);
Block->setBody(new (Context) CompoundStmt(ConvLocation));
Expr *BuildBlock = new (Context) BlockExpr(Block, Conv->getConversionType());
ExprCleanupObjects.push_back(Block);
ExprNeedsCleanups = true;
return BuildBlock;
}