summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Sema')
-rw-r--r--clang/lib/Sema/Scope.cpp24
-rw-r--r--clang/lib/Sema/SemaDecl.cpp33
-rw-r--r--clang/lib/Sema/SemaExpr.cpp10
-rw-r--r--clang/lib/Sema/SemaStmt.cpp9
-rw-r--r--clang/lib/Sema/SemaTemplateInstantiateDecl.cpp5
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;
OpenPOWER on IntegriCloud