Commit f545ede9 authored by Richard Smith's avatar Richard Smith
Browse files

Fix regression in bdad0a1b: force rebuilding of StmtExpr nodes in

TreeTransform if the 'dependent' flag would change.
parent c4119a5b
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -4965,7 +4965,9 @@ public:
  void ActOnStartStmtExpr();
  ExprResult ActOnStmtExpr(Scope *S, SourceLocation LPLoc, Stmt *SubStmt,
                           SourceLocation RPLoc); // "({..})"
                           SourceLocation RPLoc);
  ExprResult BuildStmtExpr(SourceLocation LPLoc, Stmt *SubStmt,
                           SourceLocation RPLoc, bool IsDependent);
  // Handle the final expression in a statement expression.
  ExprResult ActOnStmtExprResult(ExprResult E);
  void ActOnStmtExprError();
+8 −10
Original line number Diff line number Diff line
@@ -13912,7 +13912,13 @@ void Sema::ActOnStmtExprError() {
}
ExprResult Sema::ActOnStmtExpr(Scope *S, SourceLocation LPLoc, Stmt *SubStmt,
                               SourceLocation RPLoc) { // "({..})"
                               SourceLocation RPLoc) {
  return BuildStmtExpr(LPLoc, SubStmt, RPLoc,
                       S->getTemplateParamParent() != nullptr);
}
ExprResult Sema::BuildStmtExpr(SourceLocation LPLoc, Stmt *SubStmt,
                               SourceLocation RPLoc, bool IsDependent) {
  assert(SubStmt && isa<CompoundStmt>(SubStmt) && "Invalid action invocation!");
  CompoundStmt *Compound = cast<CompoundStmt>(SubStmt);
@@ -13941,18 +13947,10 @@ ExprResult Sema::ActOnStmtExpr(Scope *S, 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, IsDependentContext);
      new (Context) StmtExpr(Compound, Ty, LPLoc, RPLoc, IsDependent);
  if (StmtExprMayBindToTemp)
    return MaybeBindToTemporary(ResStmtExpr);
  return ResStmtExpr;
+9 −5
Original line number Diff line number Diff line
@@ -2550,8 +2550,8 @@ public:
  /// By default, performs semantic analysis to build the new expression.
  /// Subclasses may override this routine to provide different behavior.
  ExprResult RebuildStmtExpr(SourceLocation LParenLoc, Stmt *SubStmt,
                             SourceLocation RParenLoc) {
    return getSema().ActOnStmtExpr(nullptr, LParenLoc, SubStmt, RParenLoc);
                             SourceLocation RParenLoc, bool IsDependent) {
    return getSema().BuildStmtExpr(LParenLoc, SubStmt, RParenLoc, IsDependent);
  }
  /// Build a new __builtin_choose_expr expression.
@@ -10432,16 +10432,20 @@ TreeTransform<Derived>::TransformStmtExpr(StmtExpr *E) {
    return ExprError();
  }
  // FIXME: This is not correct when substituting inside a templated
  // context that isn't a DeclContext (such as a variable template).
  bool IsDependent = getSema().CurContext->isDependentContext();
  if (!getDerived().AlwaysRebuild() &&
      IsDependent == E->isInstantiationDependent() &&
      SubStmt.get() == E->getSubStmt()) {
    // Calling this an 'error' is unintuitive, but it does the right thing.
    SemaRef.ActOnStmtExprError();
    return SemaRef.MaybeBindToTemporary(E);
  }
  return getDerived().RebuildStmtExpr(E->getLParenLoc(),
                                      SubStmt.get(),
                                      E->getRParenLoc());
  return getDerived().RebuildStmtExpr(E->getLParenLoc(), SubStmt.get(),
                                      E->getRParenLoc(), IsDependent);
}
template<typename Derived>
+7 −0
Original line number Diff line number Diff line
@@ -125,4 +125,11 @@ namespace PR45083 {
  };

  template void B<int>::f();

  // Make sure we properly rebuild statement expression AST nodes even if the
  // only thing that changes is the "is dependent" flag.
  template<typename> void f() {
    decltype(({})) x; // expected-error {{incomplete type}}
  }
  template void f<int>(); // expected-note {{instantiation of}}
}