diff options
Diffstat (limited to 'clang/lib')
| -rw-r--r-- | clang/lib/AST/Decl.cpp | 16 | ||||
| -rw-r--r-- | clang/lib/CodeGen/CGStmt.cpp | 52 | ||||
| -rw-r--r-- | clang/lib/CodeGen/CodeGenFunction.h | 3 | ||||
| -rw-r--r-- | clang/lib/Sema/ScopeInfo.cpp | 8 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 22 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaStmt.cpp | 6 | ||||
| -rw-r--r-- | clang/lib/Serialization/ASTWriterStmt.cpp | 2 |
7 files changed, 66 insertions, 43 deletions
diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index 0de5459a4c1..431adaf184f 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -3283,6 +3283,11 @@ bool FieldDecl::isAnonymousStructOrUnion() const { return false; } +static bool isVLATypeCapturingAllowed(const RecordDecl *RD) { + // Allow variable-length array capturing in Lambdas and CapturedStmts. + return RD->isLambda() || RD->isCapturedRecord(); +} + unsigned FieldDecl::getBitWidthValue(const ASTContext &Ctx) const { assert(isBitField() && "not a bitfield"); Expr *BitWidth = static_cast<Expr *>(InitStorage.getPointer()); @@ -3325,7 +3330,8 @@ SourceRange FieldDecl::getSourceRange() const { } void FieldDecl::setCapturedVLAType(const VariableArrayType *VLAType) { - assert(getParent()->isLambda() && "capturing type in non-lambda."); + assert(isVLATypeCapturingAllowed(getParent()) && + "capturing type in non-lambda or captured record."); assert(InitStorage.getInt() == ISK_BitWidthOrNothing && InitStorage.getPointer() == nullptr && "bit width, initializer or captured type already set"); @@ -3559,6 +3565,14 @@ bool RecordDecl::isLambda() const { return false; } +bool RecordDecl::isCapturedRecord() const { + return hasAttr<CapturedRecordAttr>(); +} + +void RecordDecl::setCapturedRecord() { + addAttr(CapturedRecordAttr::CreateImplicit(getASTContext())); +} + RecordDecl::field_iterator RecordDecl::field_begin() const { if (hasExternalLexicalStorage() && !LoadedFieldsFromExternalStorage) LoadFieldsFromExternalStorage(); diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp index d4fd3b5178d..f207a4f7f8d 100644 --- a/clang/lib/CodeGen/CGStmt.cpp +++ b/clang/lib/CodeGen/CGStmt.cpp @@ -2102,46 +2102,35 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) { } } -static LValue InitCapturedStruct(CodeGenFunction &CGF, const CapturedStmt &S) { +LValue CodeGenFunction::InitCapturedStruct(const CapturedStmt &S) { const RecordDecl *RD = S.getCapturedRecordDecl(); - QualType RecordTy = CGF.getContext().getRecordType(RD); + QualType RecordTy = getContext().getRecordType(RD); // Initialize the captured struct. - LValue SlotLV = CGF.MakeNaturalAlignAddrLValue( - CGF.CreateMemTemp(RecordTy, "agg.captured"), RecordTy); + LValue SlotLV = MakeNaturalAlignAddrLValue( + CreateMemTemp(RecordTy, "agg.captured"), RecordTy); RecordDecl::field_iterator CurField = RD->field_begin(); for (CapturedStmt::capture_init_iterator I = S.capture_init_begin(), E = S.capture_init_end(); I != E; ++I, ++CurField) { - LValue LV = CGF.EmitLValueForFieldInitialization(SlotLV, *CurField); - CGF.EmitInitializerForField(*CurField, LV, *I, None); + LValue LV = EmitLValueForFieldInitialization(SlotLV, *CurField); + if (CurField->hasCapturedVLAType()) { + auto VAT = CurField->getCapturedVLAType(); + EmitStoreThroughLValue(RValue::get(VLASizeMap[VAT->getSizeExpr()]), LV); + } else { + EmitInitializerForField(*CurField, LV, *I, None); + } } return SlotLV; } -static void InitVLACaptures(CodeGenFunction &CGF, const CapturedStmt &S) { - for (auto &C : S.captures()) { - if (C.capturesVariable()) { - QualType QTy; - auto VD = C.getCapturedVar(); - if (const ParmVarDecl *PVD = dyn_cast<ParmVarDecl>(VD)) - QTy = PVD->getOriginalType(); - else - QTy = VD->getType(); - if (QTy->isVariablyModifiedType()) { - CGF.EmitVariablyModifiedType(QTy); - } - } - } -} - /// Generate an outlined function for the body of a CapturedStmt, store any /// captured variables into the captured struct, and call the outlined function. llvm::Function * CodeGenFunction::EmitCapturedStmt(const CapturedStmt &S, CapturedRegionKind K) { - LValue CapStruct = InitCapturedStruct(*this, S); + LValue CapStruct = InitCapturedStruct(S); // Emit the CapturedDecl CodeGenFunction CGF(CGM, true); @@ -2157,7 +2146,7 @@ CodeGenFunction::EmitCapturedStmt(const CapturedStmt &S, CapturedRegionKind K) { llvm::Value * CodeGenFunction::GenerateCapturedStmtArgument(const CapturedStmt &S) { - LValue CapStruct = InitCapturedStruct(*this, S); + LValue CapStruct = InitCapturedStruct(S); return CapStruct.getAddress(); } @@ -2198,14 +2187,21 @@ CodeGenFunction::GenerateCapturedStmtFunction(const CapturedStmt &S) { CapturedStmtInfo->setContextValue(Builder.CreateLoad(DeclPtr)); // Initialize variable-length arrays. - InitVLACaptures(*this, S); + LValue Base = MakeNaturalAlignAddrLValue(CapturedStmtInfo->getContextValue(), + Ctx.getTagDeclType(RD)); + for (auto *FD : RD->fields()) { + if (FD->hasCapturedVLAType()) { + auto *ExprArg = EmitLoadOfLValue(EmitLValueForField(Base, FD), + S.getLocStart()).getScalarVal(); + auto VAT = FD->getCapturedVLAType(); + VLASizeMap[VAT->getSizeExpr()] = ExprArg; + } + } // If 'this' is captured, load it into CXXThisValue. if (CapturedStmtInfo->isCXXThisExprCaptured()) { FieldDecl *FD = CapturedStmtInfo->getThisFieldDecl(); - LValue LV = MakeNaturalAlignAddrLValue(CapturedStmtInfo->getContextValue(), - Ctx.getTagDeclType(RD)); - LValue ThisLValue = EmitLValueForField(LV, FD); + LValue ThisLValue = EmitLValueForField(Base, FD); CXXThisValue = EmitLoadOfLValue(ThisLValue, Loc).getScalarVal(); } diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index 66f3fcecff7..eb3e6566336 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -193,7 +193,7 @@ public: I != E; ++I, ++Field) { if (I->capturesThis()) CXXThisFieldDecl = *Field; - else + else if (I->capturesVariable()) CaptureFields[I->getCapturedVar()] = *Field; } } @@ -2002,6 +2002,7 @@ public: void EmitCXXForRangeStmt(const CXXForRangeStmt &S, ArrayRef<const Attr *> Attrs = None); + LValue InitCapturedStruct(const CapturedStmt &S); llvm::Function *EmitCapturedStmt(const CapturedStmt &S, CapturedRegionKind K); void GenerateCapturedStmtFunctionProlog(const CapturedStmt &S); llvm::Function *GenerateCapturedStmtFunctionEpilog(const CapturedStmt &S); diff --git a/clang/lib/Sema/ScopeInfo.cpp b/clang/lib/Sema/ScopeInfo.cpp index 259cd674c36..c4bf67b76cd 100644 --- a/clang/lib/Sema/ScopeInfo.cpp +++ b/clang/lib/Sema/ScopeInfo.cpp @@ -95,8 +95,14 @@ FunctionScopeInfo::WeakObjectProfileTy::getBaseInfo(const Expr *E) { } bool CapturingScopeInfo::isVLATypeCaptured(const VariableArrayType *VAT) const { + RecordDecl *RD = nullptr; if (auto *LSI = dyn_cast<LambdaScopeInfo>(this)) - for (auto *FD : LSI->Lambda->fields()) { + RD = LSI->Lambda; + else if (auto CRSI = dyn_cast<CapturedRegionScopeInfo>(this)) + RD = CRSI->TheRecordDecl; + + if (RD) + for (auto *FD : RD->fields()) { if (FD->hasCapturedVLAType() && FD->getCapturedVLAType() == VAT) return true; } diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 8c13f89c0b3..a8e4407f34f 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -12219,29 +12219,29 @@ bool Sema::tryCaptureVariable(VarDecl *Var, SourceLocation ExprLoc, // Unknown size indication requires no size computation. // Otherwise, evaluate and record it. if (auto Size = VAT->getSizeExpr()) { - if (auto LSI = dyn_cast<LambdaScopeInfo>(CSI)) { - if (!LSI->isVLATypeCaptured(VAT)) { + if (!CSI->isVLATypeCaptured(VAT)) { + RecordDecl *CapRecord = nullptr; + if (auto LSI = dyn_cast<LambdaScopeInfo>(CSI)) { + CapRecord = LSI->Lambda; + } else if (auto CRSI = dyn_cast<CapturedRegionScopeInfo>(CSI)) { + CapRecord = CRSI->TheRecordDecl; + } + if (CapRecord) { auto ExprLoc = Size->getExprLoc(); auto SizeType = Context.getSizeType(); - auto Lambda = LSI->Lambda; - // Build the non-static data member. auto Field = FieldDecl::Create( - Context, Lambda, ExprLoc, ExprLoc, + Context, CapRecord, ExprLoc, ExprLoc, /*Id*/ nullptr, SizeType, /*TInfo*/ nullptr, /*BW*/ nullptr, /*Mutable*/ false, /*InitStyle*/ ICIS_NoInit); Field->setImplicit(true); Field->setAccess(AS_private); Field->setCapturedVLAType(VAT); - Lambda->addDecl(Field); + CapRecord->addDecl(Field); - LSI->addVLATypeCapture(ExprLoc, SizeType); + CSI->addVLATypeCapture(ExprLoc, SizeType); } - } else { - // Immediately mark all referenced vars for CapturedStatements, - // they all are captured by reference. - MarkDeclarationsReferencedInExpr(Size); } } QTy = VAT->getElementType(); diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp index 0c2d9e3e7a0..3c4085afe1e 100644 --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/lib/Sema/SemaStmt.cpp @@ -3385,6 +3385,7 @@ Sema::CreateCapturedStmtRecordDecl(CapturedDecl *&CD, SourceLocation Loc, else RD = RecordDecl::Create(Context, TTK_Struct, DC, Loc, Loc, /*Id=*/nullptr); + RD->setCapturedRecord(); DC->addDecl(RD); RD->setImplicit(); RD->startDefinition(); @@ -3408,6 +3409,11 @@ static void buildCapturedStmtCaptureList( CapturedStmt::VCK_This)); CaptureInits.push_back(Cap->getInitExpr()); continue; + } else if (Cap->isVLATypeCapture()) { + Captures.push_back( + CapturedStmt::Capture(Cap->getLocation(), CapturedStmt::VCK_VLAType)); + CaptureInits.push_back(nullptr); + continue; } assert(Cap->isReferenceCapture() && diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp index 99e7e6d2ef0..61ec6a058b1 100644 --- a/clang/lib/Serialization/ASTWriterStmt.cpp +++ b/clang/lib/Serialization/ASTWriterStmt.cpp @@ -307,7 +307,7 @@ void ASTStmtWriter::VisitCapturedStmt(CapturedStmt *S) { // Captures for (const auto &I : S->captures()) { - if (I.capturesThis()) + if (I.capturesThis() || I.capturesVariableArrayType()) Writer.AddDeclRef(nullptr, Record); else Writer.AddDeclRef(I.getCapturedVar(), Record); |

