Loading clang/include/clang/Sema/Sema.h +3 −1 Original line number Diff line number Diff line Loading @@ -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(); Loading clang/lib/Sema/SemaExpr.cpp +8 −10 Original line number Diff line number Diff line Loading @@ -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); Loading Loading @@ -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; clang/lib/Sema/TreeTransform.h +9 −5 Original line number Diff line number Diff line Loading @@ -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. Loading Loading @@ -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> Loading clang/test/SemaTemplate/dependent-expr.cpp +7 −0 Original line number Diff line number Diff line Loading @@ -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}} } Loading
clang/include/clang/Sema/Sema.h +3 −1 Original line number Diff line number Diff line Loading @@ -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(); Loading
clang/lib/Sema/SemaExpr.cpp +8 −10 Original line number Diff line number Diff line Loading @@ -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); Loading Loading @@ -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;
clang/lib/Sema/TreeTransform.h +9 −5 Original line number Diff line number Diff line Loading @@ -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. Loading Loading @@ -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> Loading
clang/test/SemaTemplate/dependent-expr.cpp +7 −0 Original line number Diff line number Diff line Loading @@ -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}} }