diff options
Diffstat (limited to 'clang/lib/Sema')
-rw-r--r-- | clang/lib/Sema/Scope.cpp | 24 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 33 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 10 | ||||
-rw-r--r-- | clang/lib/Sema/SemaStmt.cpp | 9 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplateInstantiateDecl.cpp | 5 |
5 files changed, 50 insertions, 31 deletions
diff --git a/clang/lib/Sema/Scope.cpp b/clang/lib/Sema/Scope.cpp index 5a46ba26d29..eae5a328bfa 100644 --- a/clang/lib/Sema/Scope.cpp +++ b/clang/lib/Sema/Scope.cpp @@ -92,6 +92,7 @@ void Scope::Init(Scope *parent, unsigned flags) { UsingDirectives.clear(); Entity = nullptr; ErrorTrap.reset(); + NRVO.setPointerAndInt(nullptr, 0); } bool Scope::containedInPrototypeScope() const { @@ -118,15 +119,19 @@ void Scope::AddFlags(unsigned FlagsToSet) { Flags |= FlagsToSet; } -void Scope::setNRVOCandidate(VarDecl *Candidate) { - for (Decl *D : DeclsInScope) { - VarDecl *VD = dyn_cast<VarDecl>(D); - if (VD && VD != Candidate && VD->isNRVOCandidate()) - VD->setNRVOVariable(false); +void Scope::mergeNRVOIntoParent() { + if (VarDecl *Candidate = NRVO.getPointer()) { + if (isDeclScope(Candidate)) + Candidate->setNRVOVariable(true); } - if (Scope *parent = getParent()) - parent->setNRVOCandidate(Candidate); + if (getEntity()) + return; + + if (NRVO.getInt()) + getParent()->setNoNRVO(); + else if (NRVO.getPointer()) + getParent()->addNRVOCandidate(NRVO.getPointer()); } LLVM_DUMP_METHOD void Scope::dump() const { dumpImpl(llvm::errs()); } @@ -186,4 +191,9 @@ void Scope::dumpImpl(raw_ostream &OS) const { OS << "MSCurManglingNumber: " << getMSCurManglingNumber() << '\n'; if (const DeclContext *DC = getEntity()) OS << "Entity : (clang::DeclContext*)" << DC << '\n'; + + if (NRVO.getInt()) + OS << "NRVO not allowed\n"; + else if (NRVO.getPointer()) + OS << "NRVO candidate : (clang::VarDecl*)" << NRVO.getPointer() << '\n'; } diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 4c98ffed71b..f6faf38c95e 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -1798,6 +1798,8 @@ static void CheckPoppedLabel(LabelDecl *L, Sema &S) { } void Sema::ActOnPopScope(SourceLocation Loc, Scope *S) { + S->mergeNRVOIntoParent(); + if (S->decl_empty()) return; assert((S->getFlags() & (Scope::DeclScope | Scope::TemplateParamScope)) && "Scope shouldn't contain decls!"); @@ -12561,24 +12563,21 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D, /// optimization. /// /// Each of the variables that is subject to the named return value -/// optimization will be marked as NRVO variable candidates in the AST, and any +/// optimization will be marked as NRVO variables in the AST, and any /// return statement that has a marked NRVO variable as its NRVO candidate can /// use the named return value optimization. /// -/// This function applies a very simplistic algorithm for NRVO: if every -/// reachable return statement in the scope of a variable has the same NRVO -/// candidate, that candidate is an NRVO variable. +/// This function applies a very simplistic algorithm for NRVO: if every return +/// statement in the scope of a variable has the same NRVO candidate, that +/// candidate is an NRVO variable. void Sema::computeNRVO(Stmt *Body, FunctionScopeInfo *Scope) { - for (ReturnStmt *Return : Scope->Returns) { - const VarDecl *Candidate = Return->getNRVOCandidate(); - if (!Candidate) - continue; - - if (Candidate->isNRVOCandidate()) - const_cast<VarDecl*>(Candidate)->setNRVOVariable(true); + ReturnStmt **Returns = Scope->Returns.data(); - if (!Candidate->isNRVOVariable()) - Return->setNRVOCandidate(nullptr); + for (unsigned I = 0, E = Scope->Returns.size(); I != E; ++I) { + if (const VarDecl *NRVOCandidate = Returns[I]->getNRVOCandidate()) { + if (!NRVOCandidate->isNRVOVariable()) + Returns[I]->setNRVOCandidate(nullptr); + } } } @@ -12713,8 +12712,12 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body, else if (CXXDestructorDecl *Destructor = dyn_cast<CXXDestructorDecl>(FD)) MarkVTableUsed(FD->getLocation(), Destructor->getParent()); - // Try to apply the named return value optimization. - computeNRVO(Body, getCurFunction()); + // Try to apply the named return value optimization. We have to check + // if we can do this here because lambdas keep return statements around + // to deduce an implicit return type. + if (FD->getReturnType()->isRecordType() && + (!getLangOpts().CPlusPlus || !FD->isDependentContext())) + computeNRVO(Body, getCurFunction()); } // GNU warning -Wmissing-prototypes: diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 220d6906954..aeedd6b1691 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -13385,9 +13385,13 @@ ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc, if (Body && getCurFunction()->HasPotentialAvailabilityViolations) DiagnoseUnguardedAvailabilityViolations(BSI->TheDecl); - // Try to apply the named return value optimization. - computeNRVO(Body, BSI); - + // Try to apply the named return value optimization. We have to check again + // if we can do this, though, because blocks keep return statements around + // to deduce an implicit return type. + if (getLangOpts().CPlusPlus && RetTy->isRecordType() && + !BSI->TheDecl->isDependentContext()) + computeNRVO(Body, BSI); + BlockExpr *Result = new (Context) BlockExpr(BSI->TheDecl, BlockTy); AnalysisBasedWarnings::Policy WP = AnalysisWarnings.getDefaultPolicy(); PopFunctionScopeInfo(&WP, Result->getBlockDecl(), Result); diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp index 04f51145104..ccf25ee9ebe 100644 --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/lib/Sema/SemaStmt.cpp @@ -3455,9 +3455,12 @@ Sema::ActOnReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp, ExpressionEvaluationContext::DiscardedStatement) return R; - VarDecl *VD = - const_cast<VarDecl*>(cast<ReturnStmt>(R.get())->getNRVOCandidate()); - CurScope->setNRVOCandidate(VD); + if (VarDecl *VD = + const_cast<VarDecl*>(cast<ReturnStmt>(R.get())->getNRVOCandidate())) { + CurScope->addNRVOCandidate(VD); + } else { + CurScope->setNoNRVO(); + } CheckJumpOutOfSEHFinally(*this, ReturnLoc, *CurScope->getFnParent()); diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index 7e38dcc7959..68857d972b5 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -740,13 +740,12 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D, SemaRef.BuildVariableInstantiation(Var, D, TemplateArgs, LateAttrs, Owner, StartingScope, InstantiatingVarTemplate); - bool NRVO = false; if (D->isNRVOVariable()) { QualType ReturnType = cast<FunctionDecl>(DC)->getReturnType(); if (SemaRef.isCopyElisionCandidate(ReturnType, Var, Sema::CES_Strict)) - NRVO = true; + Var->setNRVOVariable(true); } - Var->setNRVOVariable(NRVO); + Var->setImplicit(D->isImplicit()); return Var; |