Fix regression in bdad0a1: force rebuilding of StmtExpr nodes in
authorRichard Smith <richard@metafoo.co.uk>
Wed, 4 Mar 2020 21:18:46 +0000 (13:18 -0800)
committerRichard Smith <richard@metafoo.co.uk>
Wed, 4 Mar 2020 21:19:49 +0000 (13:19 -0800)
TreeTransform if the 'dependent' flag would change.

clang/include/clang/Sema/Sema.h
clang/lib/Sema/SemaExpr.cpp
clang/lib/Sema/TreeTransform.h
clang/test/SemaTemplate/dependent-expr.cpp

index 5739808..8e4d082 100644 (file)
@@ -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();
index 1870e44..291c38a 100644 (file)
@@ -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;
index 05b41aa..382496d 100644 (file)
@@ -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>
index e333ed9..97d157f 100644 (file)
@@ -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}}
 }