[PATCH] D44039: [Sema] Make getCurFunction() return null outside function parsing

2018-03-07 Thread Reid Kleckner via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL326965: [Sema] Make getCurFunction() return null outside 
function parsing (authored by rnk, committed by ).
Herald added a subscriber: llvm-commits.

Changed prior to commit:
  https://reviews.llvm.org/D44039?vs=137472&id=137507#toc

Repository:
  rL LLVM

https://reviews.llvm.org/D44039

Files:
  cfe/trunk/include/clang/Sema/Sema.h
  cfe/trunk/lib/Sema/AnalysisBasedWarnings.cpp
  cfe/trunk/lib/Sema/Sema.cpp
  cfe/trunk/lib/Sema/SemaDecl.cpp
  cfe/trunk/lib/Sema/SemaExpr.cpp
  cfe/trunk/lib/Sema/SemaExprCXX.cpp
  cfe/trunk/lib/Sema/SemaOpenMP.cpp
  cfe/trunk/lib/Sema/SemaStmt.cpp
  cfe/trunk/lib/Sema/SemaStmtAsm.cpp

Index: cfe/trunk/lib/Sema/Sema.cpp
===
--- cfe/trunk/lib/Sema/Sema.cpp
+++ cfe/trunk/lib/Sema/Sema.cpp
@@ -162,7 +162,7 @@
   ExpressionEvaluationContext::PotentiallyEvaluated, 0, CleanupInfo{},
   nullptr, false);
 
-  FunctionScopes.push_back(new FunctionScopeInfo(Diags));
+  PreallocatedFunctionScope.reset(new FunctionScopeInfo(Diags));
 
   // Initilization of data sharing attributes stack for OpenMP
   InitDataSharingAttributesStack();
@@ -332,11 +332,11 @@
 
 Sema::~Sema() {
   if (VisContext) FreeVisContext();
+
   // Kill all the active scopes.
-  for (unsigned I = 1, E = FunctionScopes.size(); I != E; ++I)
-delete FunctionScopes[I];
-  if (FunctionScopes.size() == 1)
-delete FunctionScopes[0];
+  for (sema::FunctionScopeInfo *FSI : FunctionScopes)
+if (FSI != PreallocatedFunctionScope.get())
+  delete FSI;
 
   // Tell the SemaConsumer to forget about us; we're going out of scope.
   if (SemaConsumer *SC = dyn_cast(&Consumer))
@@ -1340,17 +1340,13 @@
 
 /// \brief Enter a new function scope
 void Sema::PushFunctionScope() {
-  if (FunctionScopes.size() == 1) {
-// Use the "top" function scope rather than having to allocate
-// memory for a new scope.
-FunctionScopes.back()->Clear();
-FunctionScopes.push_back(FunctionScopes.back());
-if (LangOpts.OpenMP)
-  pushOpenMPFunctionRegion();
-return;
+  if (FunctionScopes.empty()) {
+// Use PreallocatedFunctionScope to avoid allocating memory when possible.
+PreallocatedFunctionScope->Clear();
+FunctionScopes.push_back(PreallocatedFunctionScope.get());
+  } else {
+FunctionScopes.push_back(new FunctionScopeInfo(getDiagnostics()));
   }
-
-  FunctionScopes.push_back(new FunctionScopeInfo(getDiagnostics()));
   if (LangOpts.OpenMP)
 pushOpenMPFunctionRegion();
 }
@@ -1370,15 +1366,15 @@
   if (LambdaScopeInfo *const LSI = getCurLambda()) {
 LSI->AutoTemplateParameterDepth = Depth;
 return;
-  } 
-  llvm_unreachable( 
+  }
+  llvm_unreachable(
   "Remove assertion if intentionally called in a non-lambda context.");
 }
 
 void Sema::PopFunctionScopeInfo(const AnalysisBasedWarnings::Policy *WP,
 const Decl *D, const BlockExpr *blkExpr) {
-  FunctionScopeInfo *Scope = FunctionScopes.pop_back_val();
   assert(!FunctionScopes.empty() && "mismatched push/pop!");
+  FunctionScopeInfo *Scope = FunctionScopes.pop_back_val();
 
   if (LangOpts.OpenMP)
 popOpenMPFunctionRegion(Scope);
@@ -1390,7 +1386,8 @@
 for (const auto &PUD : Scope->PossiblyUnreachableDiags)
   Diag(PUD.Loc, PUD.PD);
 
-  if (FunctionScopes.back() != Scope)
+  // Delete the scope unless its our preallocated scope.
+  if (Scope != PreallocatedFunctionScope.get())
 delete Scope;
 }
 
@@ -1411,6 +1408,21 @@
   return getCurFunction()->ErrorTrap.hasUnrecoverableErrorOccurred();
 }
 
+void Sema::setFunctionHasBranchIntoScope() {
+  if (!FunctionScopes.empty())
+FunctionScopes.back()->setHasBranchIntoScope();
+}
+
+void Sema::setFunctionHasBranchProtectedScope() {
+  if (!FunctionScopes.empty())
+FunctionScopes.back()->setHasBranchProtectedScope();
+}
+
+void Sema::setFunctionHasIndirectGoto() {
+  if (!FunctionScopes.empty())
+FunctionScopes.back()->setHasIndirectGoto();
+}
+
 BlockScopeInfo *Sema::getCurBlock() {
   if (FunctionScopes.empty())
 return nullptr;
Index: cfe/trunk/lib/Sema/SemaExpr.cpp
===
--- cfe/trunk/lib/Sema/SemaExpr.cpp
+++ cfe/trunk/lib/Sema/SemaExpr.cpp
@@ -13126,7 +13126,7 @@
 for (const auto &CI : Result->getBlockDecl()->captures()) {
   const VarDecl *var = CI.getVariable();
   if (var->getType().isDestructedType() != QualType::DK_none) {
-getCurFunction()->setHasBranchProtectedScope();
+setFunctionHasBranchProtectedScope();
 break;
   }
 }
Index: cfe/trunk/lib/Sema/SemaStmtAsm.cpp
===
--- cfe/trunk/lib/Sema/SemaStmtAsm.cpp
+++ cfe/trunk/lib/Sema/SemaStmtAsm.cpp
@@ -793,7 +793,7 @@
 ArrayRef Exprs,
 SourceLocation EndLoc) {
   bool IsS

[PATCH] D44039: [Sema] Make getCurFunction() return null outside function parsing

2018-03-07 Thread Reid Kleckner via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rC326965: [Sema] Make getCurFunction() return null outside 
function parsing (authored by rnk, committed by ).

Changed prior to commit:
  https://reviews.llvm.org/D44039?vs=137472&id=137506#toc

Repository:
  rC Clang

https://reviews.llvm.org/D44039

Files:
  include/clang/Sema/Sema.h
  lib/Sema/AnalysisBasedWarnings.cpp
  lib/Sema/Sema.cpp
  lib/Sema/SemaDecl.cpp
  lib/Sema/SemaExpr.cpp
  lib/Sema/SemaExprCXX.cpp
  lib/Sema/SemaOpenMP.cpp
  lib/Sema/SemaStmt.cpp
  lib/Sema/SemaStmtAsm.cpp

Index: include/clang/Sema/Sema.h
===
--- include/clang/Sema/Sema.h
+++ include/clang/Sema/Sema.h
@@ -528,12 +528,10 @@
   ///  full expression.
   llvm::SmallPtrSet MaybeODRUseExprs;
 
+  std::unique_ptr PreallocatedFunctionScope;
+
   /// \brief Stack containing information about each of the nested
   /// function, block, and method scopes that are currently active.
-  ///
-  /// This array is never empty.  Clients should ignore the first
-  /// element, which is used to cache a single FunctionScopeInfo
-  /// that's used to parse every top-level function.
   SmallVector FunctionScopes;
 
   typedef LazyVector(&Consumer))
@@ -1340,17 +1340,13 @@
 
 /// \brief Enter a new function scope
 void Sema::PushFunctionScope() {
-  if (FunctionScopes.size() == 1) {
-// Use the "top" function scope rather than having to allocate
-// memory for a new scope.
-FunctionScopes.back()->Clear();
-FunctionScopes.push_back(FunctionScopes.back());
-if (LangOpts.OpenMP)
-  pushOpenMPFunctionRegion();
-return;
+  if (FunctionScopes.empty()) {
+// Use PreallocatedFunctionScope to avoid allocating memory when possible.
+PreallocatedFunctionScope->Clear();
+FunctionScopes.push_back(PreallocatedFunctionScope.get());
+  } else {
+FunctionScopes.push_back(new FunctionScopeInfo(getDiagnostics()));
   }
-
-  FunctionScopes.push_back(new FunctionScopeInfo(getDiagnostics()));
   if (LangOpts.OpenMP)
 pushOpenMPFunctionRegion();
 }
@@ -1370,15 +1366,15 @@
   if (LambdaScopeInfo *const LSI = getCurLambda()) {
 LSI->AutoTemplateParameterDepth = Depth;
 return;
-  } 
-  llvm_unreachable( 
+  }
+  llvm_unreachable(
   "Remove assertion if intentionally called in a non-lambda context.");
 }
 
 void Sema::PopFunctionScopeInfo(const AnalysisBasedWarnings::Policy *WP,
 const Decl *D, const BlockExpr *blkExpr) {
-  FunctionScopeInfo *Scope = FunctionScopes.pop_back_val();
   assert(!FunctionScopes.empty() && "mismatched push/pop!");
+  FunctionScopeInfo *Scope = FunctionScopes.pop_back_val();
 
   if (LangOpts.OpenMP)
 popOpenMPFunctionRegion(Scope);
@@ -1390,7 +1386,8 @@
 for (const auto &PUD : Scope->PossiblyUnreachableDiags)
   Diag(PUD.Loc, PUD.PD);
 
-  if (FunctionScopes.back() != Scope)
+  // Delete the scope unless its our preallocated scope.
+  if (Scope != PreallocatedFunctionScope.get())
 delete Scope;
 }
 
@@ -1411,6 +1408,21 @@
   return getCurFunction()->ErrorTrap.hasUnrecoverableErrorOccurred();
 }
 
+void Sema::setFunctionHasBranchIntoScope() {
+  if (!FunctionScopes.empty())
+FunctionScopes.back()->setHasBranchIntoScope();
+}
+
+void Sema::setFunctionHasBranchProtectedScope() {
+  if (!FunctionScopes.empty())
+FunctionScopes.back()->setHasBranchProtectedScope();
+}
+
+void Sema::setFunctionHasIndirectGoto() {
+  if (!FunctionScopes.empty())
+FunctionScopes.back()->setHasIndirectGoto();
+}
+
 BlockScopeInfo *Sema::getCurBlock() {
   if (FunctionScopes.empty())
 return nullptr;
Index: lib/Sema/SemaExpr.cpp
===
--- lib/Sema/SemaExpr.cpp
+++ lib/Sema/SemaExpr.cpp
@@ -13126,7 +13126,7 @@
 for (const auto &CI : Result->getBlockDecl()->captures()) {
   const VarDecl *var = CI.getVariable();
   if (var->getType().isDestructedType() != QualType::DK_none) {
-getCurFunction()->setHasBranchProtectedScope();
+setFunctionHasBranchProtectedScope();
 break;
   }
 }
Index: lib/Sema/SemaStmtAsm.cpp
===
--- lib/Sema/SemaStmtAsm.cpp
+++ lib/Sema/SemaStmtAsm.cpp
@@ -793,7 +793,7 @@
 ArrayRef Exprs,
 SourceLocation EndLoc) {
   bool IsSimple = (NumOutputs != 0 || NumInputs != 0);
-  getCurFunction()->setHasBranchProtectedScope();
+  setFunctionHasBranchProtectedScope();
   MSAsmStmt *NS =
 new (Context) MSAsmStmt(Context, AsmLoc, LBraceLoc, IsSimple,
 /*IsVolatile*/ true, AsmToks, NumOutputs, NumInputs,
Index: lib/Sema/SemaStmt.cpp
===
--- lib/Sema/SemaStmt.cpp
+++ lib/Sema/SemaStmt.cpp
@@ -557,7 +557,7 @@
 return StmtError();
 
   if (IsConstexpr || isa(Cond.g

[PATCH] D44039: [Sema] Make getCurFunction() return null outside function parsing

2018-03-07 Thread John McCall via Phabricator via cfe-commits
rjmccall added a comment.

I agree that having those sites just no-op themselves is the cleanest approach.


https://reviews.llvm.org/D44039



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D44039: [Sema] Make getCurFunction() return null outside function parsing

2018-03-07 Thread Reid Kleckner via Phabricator via cfe-commits
rnk updated this revision to Diff 137472.
rnk added a comment.

Bring back Sema::setFunctionHas* methods which internally do nothing when
called outside function scope. This appears to happen in practice when parsing
invalid code involving things like statement expressions, VLAs at global scope,
etc.


https://reviews.llvm.org/D44039

Files:
  clang/include/clang/Sema/Sema.h
  clang/lib/Sema/AnalysisBasedWarnings.cpp
  clang/lib/Sema/Sema.cpp
  clang/lib/Sema/SemaDecl.cpp
  clang/lib/Sema/SemaExpr.cpp
  clang/lib/Sema/SemaExprCXX.cpp
  clang/lib/Sema/SemaOpenMP.cpp
  clang/lib/Sema/SemaStmt.cpp
  clang/lib/Sema/SemaStmtAsm.cpp

Index: clang/lib/Sema/SemaStmtAsm.cpp
===
--- clang/lib/Sema/SemaStmtAsm.cpp
+++ clang/lib/Sema/SemaStmtAsm.cpp
@@ -793,7 +793,7 @@
 ArrayRef Exprs,
 SourceLocation EndLoc) {
   bool IsSimple = (NumOutputs != 0 || NumInputs != 0);
-  getCurFunction()->setHasBranchProtectedScope();
+  setFunctionHasBranchProtectedScope();
   MSAsmStmt *NS =
 new (Context) MSAsmStmt(Context, AsmLoc, LBraceLoc, IsSimple,
 /*IsVolatile*/ true, AsmToks, NumOutputs, NumInputs,
Index: clang/lib/Sema/SemaStmt.cpp
===
--- clang/lib/Sema/SemaStmt.cpp
+++ clang/lib/Sema/SemaStmt.cpp
@@ -557,7 +557,7 @@
 return StmtError();
 
   if (IsConstexpr || isa(Cond.get().second))
-getCurFunction()->setHasBranchProtectedScope();
+setFunctionHasBranchProtectedScope();
 
   DiagnoseUnusedExprResult(thenStmt);
   DiagnoseUnusedExprResult(elseStmt);
@@ -688,7 +688,7 @@
   if (Cond.isInvalid())
 return StmtError();
 
-  getCurFunction()->setHasBranchIntoScope();
+  setFunctionHasBranchIntoScope();
 
   SwitchStmt *SS = new (Context)
   SwitchStmt(Context, InitStmt, Cond.get().first, Cond.get().second);
@@ -1873,7 +1873,7 @@
 Sema::ActOnObjCForCollectionStmt(SourceLocation ForLoc,
  Stmt *First, Expr *collection,
  SourceLocation RParenLoc) {
-  getCurFunction()->setHasBranchProtectedScope();
+  setFunctionHasBranchProtectedScope();
 
   ExprResult CollectionExprResult =
 CheckObjCForCollectionOperand(ForLoc, collection);
@@ -2784,7 +2784,7 @@
 StmtResult Sema::ActOnGotoStmt(SourceLocation GotoLoc,
SourceLocation LabelLoc,
LabelDecl *TheDecl) {
-  getCurFunction()->setHasBranchIntoScope();
+  setFunctionHasBranchIntoScope();
   TheDecl->markUsed(Context);
   return new (Context) GotoStmt(TheDecl, GotoLoc, LabelLoc);
 }
@@ -2811,7 +2811,7 @@
 return StmtError();
   E = ExprRes.get();
 
-  getCurFunction()->setHasIndirectGoto();
+  setFunctionHasIndirectGoto();
 
   return new (Context) IndirectGotoStmt(GotoLoc, StarLoc, E);
 }
@@ -3607,7 +3607,7 @@
   if (!getLangOpts().ObjCExceptions)
 Diag(AtLoc, diag::err_objc_exceptions_disabled) << "@try";
 
-  getCurFunction()->setHasBranchProtectedScope();
+  setFunctionHasBranchProtectedScope();
   unsigned NumCatchStmts = CatchStmts.size();
   return ObjCAtTryStmt::Create(Context, AtLoc, Try, CatchStmts.data(),
NumCatchStmts, Finally);
@@ -3698,7 +3698,7 @@
 Sema::ActOnObjCAtSynchronizedStmt(SourceLocation AtLoc, Expr *SyncExpr,
   Stmt *SyncBody) {
   // We can't jump into or indirect-jump out of a @synchronized block.
-  getCurFunction()->setHasBranchProtectedScope();
+  setFunctionHasBranchProtectedScope();
   return new (Context) ObjCAtSynchronizedStmt(AtLoc, SyncExpr, SyncBody);
 }
 
@@ -3714,7 +3714,7 @@
 
 StmtResult
 Sema::ActOnObjCAutoreleasePoolStmt(SourceLocation AtLoc, Stmt *Body) {
-  getCurFunction()->setHasBranchProtectedScope();
+  setFunctionHasBranchProtectedScope();
   return new (Context) ObjCAutoreleasePoolStmt(AtLoc, Body);
 }
 
Index: clang/lib/Sema/SemaOpenMP.cpp
===
--- clang/lib/Sema/SemaOpenMP.cpp
+++ clang/lib/Sema/SemaOpenMP.cpp
@@ -3572,7 +3572,7 @@
   // longjmp() and throw() must not violate the entry/exit criteria.
   CS->getCapturedDecl()->setNothrow();
 
-  getCurFunction()->setHasBranchProtectedScope();
+  setFunctionHasBranchProtectedScope();
 
   return OMPParallelDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
   DSAStack->isCancelRegion());
@@ -5281,7 +5281,7 @@
   if (checkSimdlenSafelenSpecified(*this, Clauses))
 return StmtError();
 
-  getCurFunction()->setHasBranchProtectedScope();
+  setFunctionHasBranchProtectedScope();
   return OMPSimdDirective::Create(Context, StartLoc, EndLoc, NestedLoopCount,
   Clauses, AStmt, B);
 }
@@ -5317,7 +5317,7 @@
 }
   }
 
-  getCurFunction()->setHasBranchProtectedScope();
+  setFunctionHasBranchProtectedScope();
   re

[PATCH] D44039: [Sema] Make getCurFunction() return null outside function parsing

2018-03-07 Thread Reid Kleckner via Phabricator via cfe-commits
rnk added a comment.

Thanks!




Comment at: clang/include/clang/Sema/Sema.h:1320
   sema::FunctionScopeInfo *getCurFunction() const {
-return FunctionScopes.back();
+return FunctionScopes.empty() ? nullptr : FunctionScopes.back();
   }

thakis wrote:
> The other patch description said "This means the FunctionScopes stack will 
> often be empty, which will make getCurFunction() assert" -- did you change 
> your mind, or did you mean "which will make the caller of getCurFunction() 
> crash when it uses the null pointer"?
I changed my mind after fixing the fallout caused by the assert in `.back()`. 
There are a lot of places that want to say "if we're in a function scope and we 
had a VLA or object with a destructor, then mark this as a branch protected 
scope". If the variable is in global or class scope, we don't need to mark the 
scope as branch protected, and a null check seems like the right way to express 
that.



Comment at: clang/lib/Sema/SemaDecl.cpp:11328
 
-  if (var->getType().isDestructedType() == QualType::DK_nontrivial_c_struct)
+  if (var->hasLocalStorage() &&
+  var->getType().isDestructedType() == QualType::DK_nontrivial_c_struct)

thakis wrote:
> the hasLocalStorage() check addition here seems unrelated?
This is a different way of checking if the variable is in function scope. I 
think I made this change before making getCurFunction() return nullptr.


https://reviews.llvm.org/D44039



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D44039: [Sema] Make getCurFunction() return null outside function parsing

2018-03-07 Thread Nico Weber via Phabricator via cfe-commits
thakis accepted this revision.
thakis added a comment.
This revision is now accepted and ready to land.

Good luck!

I think the forward-looking statement in https://reviews.llvm.org/D43980 about 
this change here is a bit off, see below.

The hasLocalStorage() comment below is probably the only interesting comment.




Comment at: clang/include/clang/Sema/Sema.h:1320
   sema::FunctionScopeInfo *getCurFunction() const {
-return FunctionScopes.back();
+return FunctionScopes.empty() ? nullptr : FunctionScopes.back();
   }

The other patch description said "This means the FunctionScopes stack will 
often be empty, which will make getCurFunction() assert" -- did you change your 
mind, or did you mean "which will make the caller of getCurFunction() crash 
when it uses the null pointer"?



Comment at: clang/lib/Sema/AnalysisBasedWarnings.cpp:635
 
-/// CheckFallThroughForFunctionDef - Check that we don't fall off the end of a
+/// CheckFallThroughForBody - Check that we don't fall off the end of a
 /// function that should return a value.  Check that we don't fall off the end

nit: Just remove everything up to and including the `-` – we no longer repeat 
function names in comments.



Comment at: clang/lib/Sema/SemaDecl.cpp:11328
 
-  if (var->getType().isDestructedType() == QualType::DK_nontrivial_c_struct)
+  if (var->hasLocalStorage() &&
+  var->getType().isDestructedType() == QualType::DK_nontrivial_c_struct)

the hasLocalStorage() check addition here seems unrelated?



Comment at: clang/lib/Sema/SemaExprCXX.cpp:1117
 
-  const unsigned MaxFunctionScopesIndex = FunctionScopeIndexToStopAt ?
-*FunctionScopeIndexToStopAt : FunctionScopes.size() - 1;
+  const int MaxFunctionScopesIndex = FunctionScopeIndexToStopAt
+ ? *FunctionScopeIndexToStopAt

Maybe add "// can be -1 if there's no current function scope and 
FunctionScopeIndexToStopAt is not set" since that seems pretty subtle.


https://reviews.llvm.org/D44039



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D44039: [Sema] Make getCurFunction() return null outside function parsing

2018-03-02 Thread Reid Kleckner via Phabricator via cfe-commits
rnk created this revision.
rnk added a reviewer: rsmith.

Before this patch, Sema pre-allocated a FunctionScopeInfo and kept it in
the first, always present element of the FunctionScopes stack. This
meant that Sema::getCurFunction would return a pointer to this
pre-allocated object when parsing code outside a function body. This is
pretty much always a bug, so this patch moves the pre-allocated object
into a separate unique_ptr. This should make bugs like PR36536 a lot
more obvious.

As you can see from this patch, there were a number of places that
unconditionally assumed they were always called inside a function.
However, there are also many places that null checked the result of
getCurFunction(), so I think this is a reasonable direction.


https://reviews.llvm.org/D44039

Files:
  clang/include/clang/Sema/Sema.h
  clang/lib/Sema/AnalysisBasedWarnings.cpp
  clang/lib/Sema/Sema.cpp
  clang/lib/Sema/SemaDecl.cpp
  clang/lib/Sema/SemaExprCXX.cpp

Index: clang/lib/Sema/SemaExprCXX.cpp
===
--- clang/lib/Sema/SemaExprCXX.cpp
+++ clang/lib/Sema/SemaExprCXX.cpp
@@ -1114,8 +1114,9 @@
 
   assert((!ByCopy || Explicit) && "cannot implicitly capture *this by value");
 
-  const unsigned MaxFunctionScopesIndex = FunctionScopeIndexToStopAt ?
-*FunctionScopeIndexToStopAt : FunctionScopes.size() - 1;
+  const int MaxFunctionScopesIndex = FunctionScopeIndexToStopAt
+ ? *FunctionScopeIndexToStopAt
+ : FunctionScopes.size() - 1;
 
   // Check that we can capture the *enclosing object* (referred to by '*this')
   // by the capturing-entity/closure (lambda/block/etc) at
@@ -1141,7 +1142,7 @@
 
 
   unsigned NumCapturingClosures = 0;
-  for (unsigned idx = MaxFunctionScopesIndex; idx != 0; idx--) {
+  for (int idx = MaxFunctionScopesIndex; idx >= 0; idx--) {
 if (CapturingScopeInfo *CSI =
 dyn_cast(FunctionScopes[idx])) {
   if (CSI->CXXThisCaptureIndex != 0) {
@@ -1196,8 +1197,8 @@
   // FIXME: We need to delay this marking in PotentiallyPotentiallyEvaluated
   // contexts.
   QualType ThisTy = getCurrentThisType();
-  for (unsigned idx = MaxFunctionScopesIndex; NumCapturingClosures;
-  --idx, --NumCapturingClosures) {
+  for (int idx = MaxFunctionScopesIndex; NumCapturingClosures;
+   --idx, --NumCapturingClosures) {
 CapturingScopeInfo *CSI = cast(FunctionScopes[idx]);
 Expr *ThisExpr = nullptr;
 
@@ -7176,9 +7177,6 @@
 
   const bool IsFullExprInstantiationDependent = FE->isInstantiationDependent();
 
-  ArrayRef FunctionScopesArrayRef(
-  S.FunctionScopes.data(), S.FunctionScopes.size());
-
   // All the potentially captureable variables in the current nested
   // lambda (within a generic outer lambda), must be captured by an
   // outer lambda that is enclosed within a non-dependent context.
@@ -7207,7 +7205,7 @@
 // capture the variable in that lambda (and all its enclosing lambdas).
 if (const Optional Index =
 getStackIndexOfNearestEnclosingCaptureCapableLambda(
-FunctionScopesArrayRef, Var, S)) {
+S.FunctionScopes, Var, S)) {
   const unsigned FunctionScopeIndexOfCapturableLambda = Index.getValue();
   MarkVarDeclODRUsed(Var, VarExpr->getExprLoc(), S,
  &FunctionScopeIndexOfCapturableLambda);
@@ -7243,7 +7241,7 @@
 // 'this' in that lambda (and all its enclosing lambdas).
 if (const Optional Index =
 getStackIndexOfNearestEnclosingCaptureCapableLambda(
-FunctionScopesArrayRef, /*0 is 'this'*/ nullptr, S)) {
+S.FunctionScopes, /*0 is 'this'*/ nullptr, S)) {
   const unsigned FunctionScopeIndexOfCapturableLambda = Index.getValue();
   S.CheckCXXThisCapture(CurrentLSI->PotentialThisCaptureLocation,
 /*Explicit*/ false, /*BuildAndDiagnose*/ true,
Index: clang/lib/Sema/SemaDecl.cpp
===
--- clang/lib/Sema/SemaDecl.cpp
+++ clang/lib/Sema/SemaDecl.cpp
@@ -5747,7 +5747,8 @@
   TypeSourceInfo *TInfo = NewTD->getTypeSourceInfo();
   QualType T = TInfo->getType();
   if (T->isVariablyModifiedType()) {
-getCurFunction()->setHasBranchProtectedScope();
+if (getCurFunction())
+  getCurFunction()->setHasBranchProtectedScope();
 
 if (S->getFnParent() == nullptr) {
   bool SizeIsNegative;
@@ -7407,7 +7408,8 @@
   bool isVM = T->isVariablyModifiedType();
   if (isVM || NewVD->hasAttr() ||
   NewVD->hasAttr())
-getCurFunction()->setHasBranchProtectedScope();
+if (getCurFunction())
+  getCurFunction()->setHasBranchProtectedScope();
 
   if ((isVM && NewVD->hasLinkage()) ||
   (T->isVariableArrayType() && NewVD->hasGlobalStorage())) {
@@ -10643,7 +10645,7 @@
   return;
 }
 
-if (VDecl->hasLocalStorage())
+if (VDecl->hasLocalStorage() && getCurFunction())
   get