summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema/Sema.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Sema/Sema.cpp')
-rw-r--r--clang/lib/Sema/Sema.cpp54
1 files changed, 54 insertions, 0 deletions
diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp
index 82a04e1070d..0af6d0d89cc 100644
--- a/clang/lib/Sema/Sema.cpp
+++ b/clang/lib/Sema/Sema.cpp
@@ -1398,11 +1398,65 @@ void Sema::RecordParsingTemplateParameterDepth(unsigned Depth) {
"Remove assertion if intentionally called in a non-lambda context.");
}
+// Check that the type of the VarDecl has an accessible copy constructor and
+// resolve its destructor's exception spefication.
+static void checkEscapingByref(VarDecl *VD, Sema &S) {
+ QualType T = VD->getType();
+ EnterExpressionEvaluationContext scope(
+ S, Sema::ExpressionEvaluationContext::PotentiallyEvaluated);
+ SourceLocation Loc = VD->getLocation();
+ Expr *VarRef = new (S.Context) DeclRefExpr(VD, false, T, VK_LValue, Loc);
+ ExprResult Result = S.PerformMoveOrCopyInitialization(
+ InitializedEntity::InitializeBlock(Loc, T, false), VD, VD->getType(),
+ VarRef, /*AllowNRVO=*/true);
+ if (!Result.isInvalid()) {
+ Result = S.MaybeCreateExprWithCleanups(Result);
+ Expr *Init = Result.getAs<Expr>();
+ S.Context.setBlockVarCopyInit(VD, Init, S.canThrow(Init));
+ }
+
+ // The destructor's exception spefication is needed when IRGen generates
+ // block copy/destroy functions. Resolve it here.
+ if (const CXXRecordDecl *RD = T->getAsCXXRecordDecl())
+ if (CXXDestructorDecl *DD = RD->getDestructor()) {
+ auto *FPT = DD->getType()->getAs<FunctionProtoType>();
+ S.ResolveExceptionSpec(Loc, FPT);
+ }
+}
+
+static void markEscapingByrefs(const FunctionScopeInfo &FSI, Sema &S) {
+ // Set the EscapingByref flag of __block variables captured by
+ // escaping blocks.
+ for (const BlockDecl *BD : FSI.Blocks) {
+ if (BD->doesNotEscape())
+ continue;
+ for (const BlockDecl::Capture &BC : BD->captures()) {
+ VarDecl *VD = BC.getVariable();
+ if (VD->hasAttr<BlocksAttr>())
+ VD->setEscapingByref();
+ }
+ }
+
+ for (VarDecl *VD : FSI.ByrefBlockVars) {
+ // __block variables might require us to capture a copy-initializer.
+ if (!VD->isEscapingByref())
+ continue;
+ // It's currently invalid to ever have a __block variable with an
+ // array type; should we diagnose that here?
+ // Regardless, we don't want to ignore array nesting when
+ // constructing this copy.
+ if (VD->getType()->isStructureOrClassType())
+ checkEscapingByref(VD, S);
+ }
+}
+
void Sema::PopFunctionScopeInfo(const AnalysisBasedWarnings::Policy *WP,
const Decl *D, const BlockExpr *blkExpr) {
assert(!FunctionScopes.empty() && "mismatched push/pop!");
FunctionScopeInfo *Scope = FunctionScopes.pop_back_val();
+ markEscapingByrefs(*Scope, *this);
+
if (LangOpts.OpenMP)
popOpenMPFunctionRegion(Scope);
OpenPOWER on IntegriCloud