Commit 3a843031 authored by Richard Smith's avatar Richard Smith Committed by Hans Wennborg
Browse files

PR45083: Mark statement expressions as being dependent if they appear in

dependent contexts.

We previously assumed they were neither value- nor
instantiation-dependent under any circumstances, which would lead to
crashes and other misbehavior.

(cherry picked from commit bdad0a1b)
parent bca373f7
Loading
Loading
Loading
Loading
+6 −6
Original line number Diff line number Diff line
@@ -3955,13 +3955,13 @@ class StmtExpr : public Expr {
  Stmt *SubStmt;
  SourceLocation LParenLoc, RParenLoc;
public:
  // FIXME: Does type-dependence need to be computed differently?
  // FIXME: Do we need to compute instantiation instantiation-dependence for
  // statements? (ugh!)
  StmtExpr(CompoundStmt *substmt, QualType T,
           SourceLocation lp, SourceLocation rp) :
           SourceLocation lp, SourceLocation rp, bool InDependentContext) :
    // Note: we treat a statement-expression in a dependent context as always
    // being value- and instantiation-dependent. This matches the behavior of
    // lambda-expressions and GCC.
    Expr(StmtExprClass, T, VK_RValue, OK_Ordinary,
         T->isDependentType(), false, false, false),
         T->isDependentType(), InDependentContext, InDependentContext, false),
    SubStmt(substmt), LParenLoc(lp), RParenLoc(rp) {}

  /// Build an empty statement expression.
+1 −1
Original line number Diff line number Diff line
@@ -4923,7 +4923,7 @@ public:
                            LabelDecl *TheDecl);
  void ActOnStartStmtExpr();
  ExprResult ActOnStmtExpr(SourceLocation LPLoc, Stmt *SubStmt,
  ExprResult ActOnStmtExpr(Scope *S, SourceLocation LPLoc, Stmt *SubStmt,
                           SourceLocation RPLoc); // "({..})"
  // Handle the final expression in a statement expression.
  ExprResult ActOnStmtExprResult(ExprResult E);
+3 −2
Original line number Diff line number Diff line
@@ -6724,8 +6724,9 @@ ExpectedStmt ASTNodeImporter::VisitStmtExpr(StmtExpr *E) {
  SourceLocation ToLParenLoc, ToRParenLoc;
  std::tie(ToSubStmt, ToType, ToLParenLoc, ToRParenLoc) = *Imp;

  return new (Importer.getToContext()) StmtExpr(
      ToSubStmt, ToType, ToLParenLoc, ToRParenLoc);
  return new (Importer.getToContext())
      StmtExpr(ToSubStmt, ToType, ToLParenLoc, ToRParenLoc,
               E->isInstantiationDependent());
}

ExpectedStmt ASTNodeImporter::VisitUnaryOperator(UnaryOperator *E) {
+2 −1
Original line number Diff line number Diff line
@@ -2655,7 +2655,8 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr,

      // If the substmt parsed correctly, build the AST node.
      if (!Stmt.isInvalid()) {
        Result = Actions.ActOnStmtExpr(OpenLoc, Stmt.get(), Tok.getLocation());
        Result = Actions.ActOnStmtExpr(getCurScope(), OpenLoc, Stmt.get(),
                                       Tok.getLocation());
      } else {
        Actions.ActOnStmtExprError();
      }
+12 −4
Original line number Diff line number Diff line
@@ -13908,8 +13908,7 @@ void Sema::ActOnStmtExprError() {
  PopExpressionEvaluationContext();
}
ExprResult
Sema::ActOnStmtExpr(SourceLocation LPLoc, Stmt *SubStmt,
ExprResult Sema::ActOnStmtExpr(Scope *S, SourceLocation LPLoc, Stmt *SubStmt,
                               SourceLocation RPLoc) { // "({..})"
  assert(SubStmt && isa<CompoundStmt>(SubStmt) && "Invalid action invocation!");
  CompoundStmt *Compound = cast<CompoundStmt>(SubStmt);
@@ -13939,9 +13938,18 @@ Sema::ActOnStmtExpr(SourceLocation LPLoc, Stmt *SubStmt,
    }
  }
  bool IsDependentContext = false;
  if (S)
    IsDependentContext = S->getTemplateParamParent() != nullptr;
  else
    // FIXME: This is not correct when substituting inside a templated
    // context that isn't a DeclContext (such as a variable template).
    IsDependentContext = CurContext->isDependentContext();
  // FIXME: Check that expression type is complete/non-abstract; statement
  // expressions are not lvalues.
  Expr *ResStmtExpr = new (Context) StmtExpr(Compound, Ty, LPLoc, RPLoc);
  Expr *ResStmtExpr =
      new (Context) StmtExpr(Compound, Ty, LPLoc, RPLoc, IsDependentContext);
  if (StmtExprMayBindToTemp)
    return MaybeBindToTemporary(ResStmtExpr);
  return ResStmtExpr;
Loading