[PATCH] D44039: [Sema] Make getCurFunction() return null outside function parsing
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
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
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
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
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
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
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