diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2019-05-31 00:45:09 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2019-05-31 00:45:09 +0000 |
commit | 2fdd95c1c823ebafc9286f7b730339c38636c5a8 (patch) | |
tree | ffae98dbc613c810a160202df437d4f6c607061b /clang/lib/Sema/Sema.cpp | |
parent | 4a585a3edd1c96f19b819d44df25c376e4987a44 (diff) | |
download | bcm5719-llvm-2fdd95c1c823ebafc9286f7b730339c38636c5a8.tar.gz bcm5719-llvm-2fdd95c1c823ebafc9286f7b730339c38636c5a8.zip |
Defer capture initialization for blocks until after we've left the
function scope.
This removes one of the last few cases where we build expressions in the
wrong function scope context. No functionality change intended.
llvm-svn: 362178
Diffstat (limited to 'clang/lib/Sema/Sema.cpp')
-rw-r--r-- | clang/lib/Sema/Sema.cpp | 47 |
1 files changed, 28 insertions, 19 deletions
diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp index 71b2f47ee51..1a8948b94dc 100644 --- a/clang/lib/Sema/Sema.cpp +++ b/clang/lib/Sema/Sema.cpp @@ -176,8 +176,6 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer, ExpressionEvaluationContext::PotentiallyEvaluated, 0, CleanupInfo{}, nullptr, ExpressionEvaluationContextRecord::EK_Other); - PreallocatedFunctionScope.reset(new FunctionScopeInfo(Diags)); - // Initialization of data sharing attributes stack for OpenMP InitDataSharingAttributesStack(); @@ -354,8 +352,7 @@ Sema::~Sema() { // Kill all the active scopes. for (sema::FunctionScopeInfo *FSI : FunctionScopes) - if (FSI != PreallocatedFunctionScope.get()) - delete FSI; + delete FSI; // Tell the SemaConsumer to forget about us; we're going out of scope. if (SemaConsumer *SC = dyn_cast<SemaConsumer>(&Consumer)) @@ -1596,10 +1593,10 @@ Scope *Sema::getScopeForContext(DeclContext *Ctx) { /// Enter a new function scope void Sema::PushFunctionScope() { - if (FunctionScopes.empty()) { - // Use PreallocatedFunctionScope to avoid allocating memory when possible. - PreallocatedFunctionScope->Clear(); - FunctionScopes.push_back(PreallocatedFunctionScope.get()); + if (FunctionScopes.empty() && CachedFunctionScope) { + // Use CachedFunctionScope to avoid allocating memory when possible. + CachedFunctionScope->Clear(); + FunctionScopes.push_back(CachedFunctionScope.release()); } else { FunctionScopes.push_back(new FunctionScopeInfo(getDiagnostics())); } @@ -1680,30 +1677,42 @@ static void markEscapingByrefs(const FunctionScopeInfo &FSI, Sema &S) { } } -void Sema::PopFunctionScopeInfo(const AnalysisBasedWarnings::Policy *WP, - const Decl *D, const BlockExpr *blkExpr) { +/// Pop a function (or block or lambda or captured region) scope from the stack. +/// +/// \param WP The warning policy to use for CFG-based warnings, or null if such +/// warnings should not be produced. +/// \param D The declaration corresponding to this function scope, if producing +/// CFG-based warnings. +/// \param BlockType The type of the block expression, if D is a BlockDecl. +Sema::PoppedFunctionScopePtr +Sema::PopFunctionScopeInfo(const AnalysisBasedWarnings::Policy *WP, + const Decl *D, QualType BlockType) { assert(!FunctionScopes.empty() && "mismatched push/pop!"); - // This function shouldn't be called after popping the current function scope. - // markEscapingByrefs calls PerformMoveOrCopyInitialization, which can call - // PushFunctionScope, which can cause clearing out PreallocatedFunctionScope - // when FunctionScopes is empty. markEscapingByrefs(*FunctionScopes.back(), *this); - FunctionScopeInfo *Scope = FunctionScopes.pop_back_val(); + PoppedFunctionScopePtr Scope(FunctionScopes.pop_back_val(), + PoppedFunctionScopeDeleter(this)); if (LangOpts.OpenMP) - popOpenMPFunctionRegion(Scope); + popOpenMPFunctionRegion(Scope.get()); // Issue any analysis-based warnings. if (WP && D) - AnalysisWarnings.IssueWarnings(*WP, Scope, D, blkExpr); + AnalysisWarnings.IssueWarnings(*WP, Scope.get(), D, BlockType); else for (const auto &PUD : Scope->PossiblyUnreachableDiags) Diag(PUD.Loc, PUD.PD); - // Delete the scope unless its our preallocated scope. - if (Scope != PreallocatedFunctionScope.get()) + return Scope; +} + +void Sema::PoppedFunctionScopeDeleter:: +operator()(sema::FunctionScopeInfo *Scope) const { + // Stash the function scope for later reuse if it's for a normal function. + if (Scope->isPlainFunction() && !Self->CachedFunctionScope) + Self->CachedFunctionScope.reset(Scope); + else delete Scope; } |