summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema/SemaExpr.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Sema/SemaExpr.cpp')
-rw-r--r--clang/lib/Sema/SemaExpr.cpp107
1 files changed, 35 insertions, 72 deletions
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index b992f3387eb..00b4cddc6b2 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -13301,29 +13301,6 @@ ExprResult Sema::ActOnAddrLabel(SourceLocation OpLoc, SourceLocation LabLoc,
Context.getPointerType(Context.VoidTy));
}
-/// Given the last statement in a statement-expression, check whether
-/// the result is a producing expression (like a call to an
-/// ns_returns_retained function) and, if so, rebuild it to hoist the
-/// release out of the full-expression. Otherwise, return null.
-/// Cannot fail.
-static Expr *maybeRebuildARCConsumingStmt(Stmt *Statement) {
- // Should always be wrapped with one of these.
- ExprWithCleanups *cleanups = dyn_cast<ExprWithCleanups>(Statement);
- if (!cleanups) return nullptr;
-
- ImplicitCastExpr *cast = dyn_cast<ImplicitCastExpr>(cleanups->getSubExpr());
- if (!cast || cast->getCastKind() != CK_ARCConsumeObject)
- return nullptr;
-
- // Splice out the cast. This shouldn't modify any interesting
- // features of the statement.
- Expr *producer = cast->getSubExpr();
- assert(producer->getType() == cast->getType());
- assert(producer->getValueKind() == cast->getValueKind());
- cleanups->setSubExpr(producer);
- return cleanups;
-}
-
void Sema::ActOnStartStmtExpr() {
PushExpressionEvaluationContext(ExprEvalContexts.back().Context);
}
@@ -13357,47 +13334,10 @@ Sema::ActOnStmtExpr(SourceLocation LPLoc, Stmt *SubStmt,
QualType Ty = Context.VoidTy;
bool StmtExprMayBindToTemp = false;
if (!Compound->body_empty()) {
- Stmt *LastStmt = Compound->body_back();
- LabelStmt *LastLabelStmt = nullptr;
- // If LastStmt is a label, skip down through into the body.
- while (LabelStmt *Label = dyn_cast<LabelStmt>(LastStmt)) {
- LastLabelStmt = Label;
- LastStmt = Label->getSubStmt();
- }
-
- if (Expr *LastE = dyn_cast<Expr>(LastStmt)) {
- // Do function/array conversion on the last expression, but not
- // lvalue-to-rvalue. However, initialize an unqualified type.
- ExprResult LastExpr = DefaultFunctionArrayConversion(LastE);
- if (LastExpr.isInvalid())
- return ExprError();
- Ty = LastExpr.get()->getType().getUnqualifiedType();
-
- if (!Ty->isDependentType() && !LastExpr.get()->isTypeDependent()) {
- // In ARC, if the final expression ends in a consume, splice
- // the consume out and bind it later. In the alternate case
- // (when dealing with a retainable type), the result
- // initialization will create a produce. In both cases the
- // result will be +1, and we'll need to balance that out with
- // a bind.
- if (Expr *rebuiltLastStmt
- = maybeRebuildARCConsumingStmt(LastExpr.get())) {
- LastExpr = rebuiltLastStmt;
- } else {
- LastExpr = PerformCopyInitialization(
- InitializedEntity::InitializeStmtExprResult(LPLoc, Ty),
- SourceLocation(), LastExpr);
- }
-
- if (LastExpr.isInvalid())
- return ExprError();
- if (LastExpr.get() != nullptr) {
- if (!LastLabelStmt)
- Compound->setLastStmt(LastExpr.get());
- else
- LastLabelStmt->setSubStmt(LastExpr.get());
- StmtExprMayBindToTemp = true;
- }
+ if (const auto *LastStmt = dyn_cast<ValueStmt>(Compound->body_back())) {
+ if (const Expr *Value = LastStmt->getExprStmt()) {
+ StmtExprMayBindToTemp = true;
+ Ty = Value->getType();
}
}
}
@@ -13410,6 +13350,37 @@ Sema::ActOnStmtExpr(SourceLocation LPLoc, Stmt *SubStmt,
return ResStmtExpr;
}
+ExprResult Sema::ActOnStmtExprResult(ExprResult ER) {
+ if (ER.isInvalid())
+ return ExprError();
+
+ // Do function/array conversion on the last expression, but not
+ // lvalue-to-rvalue. However, initialize an unqualified type.
+ ER = DefaultFunctionArrayConversion(ER.get());
+ if (ER.isInvalid())
+ return ExprError();
+ Expr *E = ER.get();
+
+ if (E->isTypeDependent())
+ return E;
+
+ // In ARC, if the final expression ends in a consume, splice
+ // the consume out and bind it later. In the alternate case
+ // (when dealing with a retainable type), the result
+ // initialization will create a produce. In both cases the
+ // result will be +1, and we'll need to balance that out with
+ // a bind.
+ auto *Cast = dyn_cast<ImplicitCastExpr>(E);
+ if (Cast && Cast->getCastKind() == CK_ARCConsumeObject)
+ return Cast->getSubExpr();
+
+ // FIXME: Provide a better location for the initialization.
+ return PerformCopyInitialization(
+ InitializedEntity::InitializeStmtExprResult(
+ E->getBeginLoc(), E->getType().getUnqualifiedType()),
+ SourceLocation(), E);
+}
+
ExprResult Sema::BuildBuiltinOffsetOf(SourceLocation BuiltinLoc,
TypeSourceInfo *TInfo,
ArrayRef<OffsetOfComponent> Components,
@@ -14490,14 +14461,6 @@ namespace {
// Make sure we redo semantic analysis
bool AlwaysRebuild() { return true; }
- // Make sure we handle LabelStmts correctly.
- // FIXME: This does the right thing, but maybe we need a more general
- // fix to TreeTransform?
- StmtResult TransformLabelStmt(LabelStmt *S) {
- S->getDecl()->setStmt(nullptr);
- return BaseTransform::TransformLabelStmt(S);
- }
-
// We need to special-case DeclRefExprs referring to FieldDecls which
// are not part of a member pointer formation; normal TreeTransforming
// doesn't catch this case because of the way we represent them in the AST.
OpenPOWER on IntegriCloud