diff options
Diffstat (limited to 'lib/Sema')
-rw-r--r-- | lib/Sema/Sema.cpp | 7 | ||||
-rw-r--r-- | lib/Sema/SemaExprCXX.cpp | 66 | ||||
-rw-r--r-- | lib/Sema/SemaType.cpp | 3 |
3 files changed, 62 insertions, 14 deletions
diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp index 6a77d8c673..4ab960de0e 100644 --- a/lib/Sema/Sema.cpp +++ b/lib/Sema/Sema.cpp @@ -869,6 +869,13 @@ BlockScopeInfo *Sema::getCurBlock() { return dyn_cast<BlockScopeInfo>(FunctionScopes.back()); } +LambdaScopeInfo *Sema::getCurLambda() { + if (FunctionScopes.empty()) + return 0; + + return dyn_cast<LambdaScopeInfo>(FunctionScopes.back()); +} + // Pin this vtable to this file. ExternalSemaSource::~ExternalSemaSource() {} diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index fd47dc75b2..0b1dcbda4f 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -4782,7 +4782,7 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro, Declarator &ParamInfo, Scope *CurScope) { DeclContext *DC = CurContext; - while (!(DC->isFunctionOrMethod() || DC->isRecord() || DC->isNamespace())) + while (!(DC->isFunctionOrMethod() || DC->isRecord() || DC->isFileContext())) DC = DC->getParent(); // Start constructing the lambda class. @@ -4795,8 +4795,26 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro, // Build the call operator; we don't really have all the relevant information // at this point, but we need something to attach child declarations to. + QualType MethodTy; TypeSourceInfo *MethodTyInfo; - MethodTyInfo = GetTypeForDeclarator(ParamInfo, CurScope); + if (ParamInfo.getNumTypeObjects() == 0) { + FunctionProtoType::ExtProtoInfo EPI; + EPI.TypeQuals |= DeclSpec::TQ_const; + MethodTy = Context.getFunctionType(Context.DependentTy, + /*Args=*/0, /*NumArgs=*/0, EPI); + MethodTyInfo = Context.getTrivialTypeSourceInfo(MethodTy); + } 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); + // FIXME: Can these asserts actually fail? + assert(MethodTyInfo && "no type from lambda-declarator"); + MethodTy = MethodTyInfo->getType(); + assert(!MethodTy.isNull() && "no type from lambda declarator"); + } DeclarationName MethodName = Context.DeclarationNames.getCXXOperatorName(OO_Call); @@ -4806,7 +4824,7 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro, ParamInfo.getSourceRange().getEnd(), DeclarationNameInfo(MethodName, /*NameLoc=*/SourceLocation()), - MethodTyInfo->getType(), + MethodTy, MethodTyInfo, /*isStatic=*/false, SC_None, @@ -4817,6 +4835,19 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro, Class->addDecl(Method); Method->setLexicalDeclContext(DC); // FIXME: Is this really correct? + ProcessDeclAttributes(CurScope, Method, ParamInfo); + + // Introduce the lambda scope. + PushLambdaScope(Class); + + // Enter a new evaluation context to insulate the block from any + // cleanups from the enclosing full-expression. + PushExpressionEvaluationContext(PotentiallyEvaluated); + + PushDeclContext(CurScope, Method); + + LambdaScopeInfo *LSI = getCurLambda(); + // Set the parameters on the decl, if specified. if (isa<FunctionProtoTypeLoc>(MethodTyInfo->getTypeLoc())) { FunctionProtoTypeLoc Proto = @@ -4825,21 +4856,30 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro, CheckParmsForFunctionDef(Method->param_begin(), Method->param_end(), /*CheckParameterNames=*/false); - } - ProcessDeclAttributes(CurScope, Method, ParamInfo); + // Introduce our parameters into the function scope + for (unsigned p = 0, NumParams = Method->getNumParams(); p < NumParams; ++p) { + ParmVarDecl *Param = Method->getParamDecl(p); + Param->setOwningFunction(Method); - // FIXME: There's a bunch of missing checking etc; - // see ActOnBlockArguments + // If this has an identifier, add it to the scope stack. + if (Param->getIdentifier()) { + CheckShadow(CurScope, Param); - // Introduce the lambda scope. - PushLambdaScope(Class); + PushOnScopeChains(Param, CurScope); + } + } + } - // Enter a new evaluation context to insulate the block from any - // cleanups from the enclosing full-expression. - PushExpressionEvaluationContext(PotentiallyEvaluated); + const FunctionType *Fn = MethodTy->getAs<FunctionType>(); + QualType RetTy = Fn->getResultType(); + if (RetTy != Context.DependentTy) { + LSI->ReturnType = RetTy; + LSI->HasImplicitReturnType = true; + } - PushDeclContext(CurScope, Method); + // FIXME: Check return type is complete, !isObjCObjectType + } void Sema::ActOnLambdaError(SourceLocation StartLoc, Scope *CurScope) { diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index a3b6768961..3bdb3b6d2c 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -2378,7 +2378,8 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, // top-level template type arguments. bool FreeFunction; if (!D.getCXXScopeSpec().isSet()) { - FreeFunction = (D.getContext() != Declarator::MemberContext || + FreeFunction = ((D.getContext() != Declarator::MemberContext && + D.getContext() != Declarator::LambdaExprContext) || D.getDeclSpec().isFriendSpecified()); } else { DeclContext *DC = S.computeDeclContext(D.getCXXScopeSpec()); |