diff options
Diffstat (limited to 'lib/Sema/SemaStmt.cpp')
-rw-r--r-- | lib/Sema/SemaStmt.cpp | 111 |
1 files changed, 111 insertions, 0 deletions
diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp index b3558a548b..88237b08b2 100644 --- a/lib/Sema/SemaStmt.cpp +++ b/lib/Sema/SemaStmt.cpp @@ -2403,6 +2403,10 @@ Sema::ActOnCapScopeReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { Diag(ReturnLoc, diag::err_noreturn_block_has_return_expr); return StmtError(); } + } else if (CapturedRegionScopeInfo *CurRegion = + dyn_cast<CapturedRegionScopeInfo>(CurCap)) { + Diag(ReturnLoc, diag::err_return_in_captured_stmt) << CurRegion->getRegionName(); + return StmtError(); } else { LambdaScopeInfo *LSI = cast<LambdaScopeInfo>(CurCap); if (LSI->CallOperator->getType()->getAs<FunctionType>()->getNoReturnAttr()){ @@ -2914,3 +2918,110 @@ StmtResult Sema::ActOnMSDependentExistsStmt(SourceLocation KeywordLoc, GetNameFromUnqualifiedId(Name), Nested); } + +RecordDecl* +Sema::CreateCapturedStmtRecordDecl(CapturedDecl *&CD, SourceLocation Loc) +{ + DeclContext *DC = CurContext; + while (!(DC->isFunctionOrMethod() || DC->isRecord() || DC->isFileContext())) + DC = DC->getParent(); + + RecordDecl *RD = 0; + if (getLangOpts().CPlusPlus) + RD = CXXRecordDecl::Create(Context, TTK_Struct, DC, Loc, Loc, /*Id=*/0); + else + RD = RecordDecl::Create(Context, TTK_Struct, DC, Loc, Loc, /*Id=*/0); + + DC->addDecl(RD); + RD->setImplicit(); + RD->startDefinition(); + + CD = CapturedDecl::Create(Context, CurContext); + DC->addDecl(CD); + + return RD; +} + +static void buildCapturedStmtCaptureList( + SmallVectorImpl<CapturedStmt::Capture> &Captures, + SmallVectorImpl<Expr *> &CaptureInits, + ArrayRef<CapturingScopeInfo::Capture> Candidates) { + + typedef ArrayRef<CapturingScopeInfo::Capture>::const_iterator CaptureIter; + for (CaptureIter Cap = Candidates.begin(); Cap != Candidates.end(); ++Cap) { + + if (Cap->isThisCapture()) { + Captures.push_back(CapturedStmt::Capture(Cap->getLocation(), + CapturedStmt::VCK_This)); + CaptureInits.push_back(Cap->getCopyExpr()); + continue; + } + + assert(Cap->isReferenceCapture() && + "non-reference capture not yet implemented"); + + Captures.push_back(CapturedStmt::Capture(Cap->getLocation(), + CapturedStmt::VCK_ByRef, + Cap->getVariable())); + CaptureInits.push_back(Cap->getCopyExpr()); + } +} + +void Sema::ActOnCapturedRegionStart(SourceLocation Loc, Scope *CurScope, + CapturedRegionScopeInfo::CapturedRegionKind Kind) { + CapturedDecl *CD = 0; + RecordDecl *RD = CreateCapturedStmtRecordDecl(CD, Loc); + + // Enter the capturing scope for this captured region. + PushCapturedRegionScope(CurScope, CD, RD, Kind); + + if (CurScope) + PushDeclContext(CurScope, CD); + else + CurContext = CD; + + PushExpressionEvaluationContext(PotentiallyEvaluated); +} + +void Sema::ActOnCapturedRegionError(bool IsInstantiation) { + DiscardCleanupsInEvaluationContext(); + PopExpressionEvaluationContext(); + + if (!IsInstantiation) + PopDeclContext(); + + CapturedRegionScopeInfo *RSI = getCurCapturedRegion(); + RecordDecl *Record = RSI->TheRecordDecl; + Record->setInvalidDecl(); + + SmallVector<Decl*, 4> Fields; + for (RecordDecl::field_iterator I = Record->field_begin(), + E = Record->field_end(); I != E; ++I) + Fields.push_back(*I); + ActOnFields(/*Scope=*/0, Record->getLocation(), Record, Fields, + SourceLocation(), SourceLocation(), /*AttributeList=*/0); + + PopFunctionScopeInfo(); +} + +StmtResult Sema::ActOnCapturedRegionEnd(Stmt *S) { + CapturedRegionScopeInfo *RSI = getCurCapturedRegion(); + + SmallVector<CapturedStmt::Capture, 4> Captures; + SmallVector<Expr *, 4> CaptureInits; + buildCapturedStmtCaptureList(Captures, CaptureInits, RSI->Captures); + + CapturedDecl *CD = RSI->TheCapturedDecl; + RecordDecl *RD = RSI->TheRecordDecl; + + CapturedStmt *Res = CapturedStmt::Create(getASTContext(), S, Captures, + CaptureInits, CD, RD); + + CD->setBody(Res->getCapturedStmt()); + RD->completeDefinition(); + + PopDeclContext(); + PopFunctionScopeInfo(); + + return Owned(Res); +} |