diff options
Diffstat (limited to 'clang/lib/Sema')
| -rw-r--r-- | clang/lib/Sema/ScopeInfo.cpp | 10 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 4 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 41 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaLambda.cpp | 6 | ||||
| -rw-r--r-- | clang/lib/Sema/TreeTransform.h | 4 |
5 files changed, 54 insertions, 11 deletions
diff --git a/clang/lib/Sema/ScopeInfo.cpp b/clang/lib/Sema/ScopeInfo.cpp index 4d079e705f6..259cd674c36 100644 --- a/clang/lib/Sema/ScopeInfo.cpp +++ b/clang/lib/Sema/ScopeInfo.cpp @@ -14,6 +14,7 @@ #include "clang/Sema/ScopeInfo.h" #include "clang/AST/Decl.h" +#include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" @@ -93,6 +94,15 @@ FunctionScopeInfo::WeakObjectProfileTy::getBaseInfo(const Expr *E) { return BaseInfoTy(D, IsExact); } +bool CapturingScopeInfo::isVLATypeCaptured(const VariableArrayType *VAT) const { + if (auto *LSI = dyn_cast<LambdaScopeInfo>(this)) + for (auto *FD : LSI->Lambda->fields()) { + if (FD->hasCapturedVLAType() && FD->getCapturedVLAType() == VAT) + return true; + } + return false; +} + FunctionScopeInfo::WeakObjectProfileTy::WeakObjectProfileTy( const ObjCPropertyRefExpr *PropE) : Base(nullptr, true), Property(getBestPropertyDecl(PropE)) { diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index c7af3b488c4..e02fa268378 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -9959,6 +9959,7 @@ static void RebuildLambdaScopeInfo(CXXMethodDecl *CallOperator, // Add the captures to the LSI so they can be noted as already // captured within tryCaptureVar. + auto I = LambdaClass->field_begin(); for (const auto &C : LambdaClass->captures()) { if (C.capturesVariable()) { VarDecl *VD = C.getCapturedVar(); @@ -9975,7 +9976,10 @@ static void RebuildLambdaScopeInfo(CXXMethodDecl *CallOperator, } else if (C.capturesThis()) { LSI->addThisCapture(/*Nested*/ false, C.getLocation(), S.getCurrentThisType(), /*Expr*/ nullptr); + } else { + LSI->addVLATypeCapture(C.getLocation(), I->getType()); } + ++I; } } diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 6a530c71ec2..d9278863534 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -11681,13 +11681,10 @@ static bool isVariableCapturable(CapturingScopeInfo *CSI, VarDecl *Var, return false; } - // Prohibit variably-modified types; they're difficult to deal with. - if (Var->getType()->isVariablyModifiedType() && (IsBlock || IsLambda)) { + // Prohibit variably-modified types in blocks; they're difficult to deal with. + if (Var->getType()->isVariablyModifiedType() && IsBlock) { if (Diagnose) { - if (IsBlock) - S.Diag(Loc, diag::err_ref_vm_type); - else - S.Diag(Loc, diag::err_lambda_capture_vm_type) << Var->getDeclName(); + S.Diag(Loc, diag::err_ref_vm_type); S.Diag(Var->getLocation(), diag::note_previous_decl) << Var->getDeclName(); } @@ -12091,7 +12088,6 @@ static bool captureInLambda(LambdaScopeInfo *LSI, return true; } - bool Sema::tryCaptureVariable(VarDecl *Var, SourceLocation ExprLoc, TryCaptureKind Kind, SourceLocation EllipsisLoc, bool BuildAndDiagnose, @@ -12228,14 +12224,37 @@ bool Sema::tryCaptureVariable(VarDecl *Var, SourceLocation ExprLoc, break; case Type::VariableArray: { // Losing element qualification here is fine. - const VariableArrayType *Vat = cast<VariableArrayType>(Ty); + const VariableArrayType *VAT = cast<VariableArrayType>(Ty); // Unknown size indication requires no size computation. // Otherwise, evaluate and record it. - if (Expr *Size = Vat->getSizeExpr()) { - MarkDeclarationsReferencedInExpr(Size); + if (auto Size = VAT->getSizeExpr()) { + if (auto LSI = dyn_cast<LambdaScopeInfo>(CSI)) { + if (!LSI->isVLATypeCaptured(VAT)) { + 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, + /*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); + + LSI->addVLATypeCapture(ExprLoc, SizeType); + } + } else { + // Immediately mark all referenced vars for CapturedStatements, + // they all are captured by reference. + MarkDeclarationsReferencedInExpr(Size); + } } - QTy = Vat->getElementType(); + QTy = VAT->getElementType(); break; } case Type::FunctionProto: diff --git a/clang/lib/Sema/SemaLambda.cpp b/clang/lib/Sema/SemaLambda.cpp index 6793bef7576..2b2b16d3bd4 100644 --- a/clang/lib/Sema/SemaLambda.cpp +++ b/clang/lib/Sema/SemaLambda.cpp @@ -1414,6 +1414,12 @@ ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body, /*isImplicit=*/true)); continue; } + if (From.isVLATypeCapture()) { + Captures.push_back( + LambdaCapture(From.getLocation(), IsImplicit, LCK_VLAType)); + CaptureInits.push_back(nullptr); + continue; + } VarDecl *Var = From.getVariable(); LambdaCaptureKind Kind = From.isCopyCapture()? LCK_ByCopy : LCK_ByRef; diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 4ba7bdf3da5..f339d507018 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -9002,6 +9002,10 @@ TreeTransform<Derived>::TransformLambdaScope(LambdaExpr *E, getSema().CheckCXXThisCapture(C->getLocation(), C->isExplicit()); continue; } + // Captured expression will be recaptured during captured variables + // rebuilding. + if (C->capturesVLAType()) + continue; // Rebuild init-captures, including the implied field declaration. if (C->isInitCapture()) { |

