@@ -3850,7 +3850,20 @@ class SingleValueStmtUsageChecker final : public ASTWalker {
38503850 llvm::DenseSet<SingleValueStmtExpr *> ValidSingleValueStmtExprs;
38513851
38523852public:
3853- SingleValueStmtUsageChecker (ASTContext &ctx) : Ctx(ctx), Diags(ctx.Diags) {}
3853+ SingleValueStmtUsageChecker (
3854+ ASTContext &ctx, ASTNode root,
3855+ llvm::Optional<ContextualTypePurpose> contextualPurpose)
3856+ : Ctx(ctx), Diags(ctx.Diags) {
3857+ assert (!root.is <Expr *>() || contextualPurpose &&
3858+ " Must provide contextual purpose for expr" );
3859+
3860+ // If we have a contextual purpose, this is for an expression. Check if it's
3861+ // an expression in a valid position.
3862+ if (contextualPurpose) {
3863+ markAnyValidTopLevelSingleValueStmt (root.get <Expr *>(),
3864+ *contextualPurpose);
3865+ }
3866+ }
38543867
38553868private:
38563869 // / Mark a given expression as a valid position for a SingleValueStmtExpr.
@@ -3862,8 +3875,23 @@ class SingleValueStmtUsageChecker final : public ASTWalker {
38623875 ValidSingleValueStmtExprs.insert (SVE);
38633876 }
38643877
3878+ // / Mark a valid top-level expression with a given contextual purpose.
3879+ void markAnyValidTopLevelSingleValueStmt (Expr *E, ContextualTypePurpose ctp) {
3880+ // Allowed in returns, throws, and bindings.
3881+ switch (ctp) {
3882+ case CTP_ReturnStmt:
3883+ case CTP_ReturnSingleExpr:
3884+ case CTP_ThrowStmt:
3885+ case CTP_Initialization:
3886+ markValidSingleValueStmt (E);
3887+ break ;
3888+ default :
3889+ break ;
3890+ }
3891+ }
3892+
38653893 MacroWalking getMacroWalkingBehavior () const override {
3866- return MacroWalking::Expansion ;
3894+ return MacroWalking::ArgumentsAndExpansion ;
38673895 }
38683896
38693897 AssignExpr *findAssignment (Expr *E) const {
@@ -3989,28 +4017,33 @@ class SingleValueStmtUsageChecker final : public ASTWalker {
39894017 if (auto *PBD = dyn_cast<PatternBindingDecl>(D)) {
39904018 for (auto idx : range (PBD->getNumPatternEntries ()))
39914019 markValidSingleValueStmt (PBD->getInit (idx));
4020+
4021+ return Action::Continue ();
39924022 }
3993- // Valid as a single expression body of a function. This is needed in
3994- // addition to ReturnStmt checking, as we will remove the return if the
3995- // expression is inferred to be Never.
3996- if (auto *AFD = dyn_cast<AbstractFunctionDecl>(D)) {
3997- if (AFD->hasSingleExpressionBody ())
3998- markValidSingleValueStmt (AFD->getSingleExpressionBody ());
3999- }
4000- return Action::Continue ();
4023+ // We don't want to walk into any other decl, we will visit them as part of
4024+ // typeCheckDecl.
4025+ return Action::SkipChildren ();
40014026 }
40024027};
40034028} // end anonymous namespace
40044029
4030+ void swift::diagnoseOutOfPlaceExprs (
4031+ ASTContext &ctx, ASTNode root,
4032+ llvm::Optional<ContextualTypePurpose> contextualPurpose) {
4033+ // TODO: We ought to consider moving this into pre-checking such that we can
4034+ // still diagnose on invalid code, and don't have to traverse over implicit
4035+ // exprs. We need to first separate out SequenceExpr folding though.
4036+ SingleValueStmtUsageChecker sveChecker (ctx, root, contextualPurpose);
4037+ root.walk (sveChecker);
4038+ }
4039+
40054040// / Apply the warnings managed by VarDeclUsageChecker to the top level
40064041// / code declarations that haven't been checked yet.
40074042void swift::
40084043performTopLevelDeclDiagnostics (TopLevelCodeDecl *TLCD) {
40094044 auto &ctx = TLCD->getDeclContext ()->getASTContext ();
40104045 VarDeclUsageChecker checker (TLCD, ctx.Diags );
40114046 TLCD->walk (checker);
4012- SingleValueStmtUsageChecker sveChecker (ctx);
4013- TLCD->walk (sveChecker);
40144047}
40154048
40164049// / Perform diagnostics for func/init/deinit declarations.
@@ -4026,10 +4059,6 @@ void swift::performAbstractFuncDeclDiagnostics(AbstractFunctionDecl *AFD) {
40264059 auto &ctx = AFD->getDeclContext ()->getASTContext ();
40274060 VarDeclUsageChecker checker (AFD, ctx.Diags );
40284061 AFD->walk (checker);
4029-
4030- // Do a similar walk to check for out of place SingleValueStmtExprs.
4031- SingleValueStmtUsageChecker sveChecker (ctx);
4032- AFD->walk (sveChecker);
40334062 }
40344063
40354064 auto *body = AFD->getBody ();
@@ -5864,10 +5893,10 @@ diagnoseDictionaryLiteralDuplicateKeyEntries(const Expr *E,
58645893// ===----------------------------------------------------------------------===//
58655894
58665895// / Emit diagnostics for syntactic restrictions on a given expression.
5867- void swift::performSyntacticExprDiagnostics (const Expr *E,
5868- const DeclContext *DC,
5869- bool isExprStmt,
5870- bool disableExprAvailabilityChecking ) {
5896+ void swift::performSyntacticExprDiagnostics (
5897+ const Expr *E, const DeclContext *DC,
5898+ llvm::Optional<ContextualTypePurpose> contextualPurpose, bool isExprStmt,
5899+ bool disableExprAvailabilityChecking, bool disableOutOfPlaceExprChecking ) {
58715900 auto &ctx = DC->getASTContext ();
58725901 TypeChecker::diagnoseSelfAssignment (E);
58735902 diagSyntacticUseRestrictions (E, DC, isExprStmt);
@@ -5886,6 +5915,8 @@ void swift::performSyntacticExprDiagnostics(const Expr *E,
58865915 diagnoseConstantArgumentRequirement (E, DC);
58875916 diagUnqualifiedAccessToMethodNamedSelf (E, DC);
58885917 diagnoseDictionaryLiteralDuplicateKeyEntries (E, DC);
5918+ if (!disableOutOfPlaceExprChecking)
5919+ diagnoseOutOfPlaceExprs (ctx, const_cast <Expr *>(E), contextualPurpose);
58895920}
58905921
58915922void swift::performStmtDiagnostics (const Stmt *S, DeclContext *DC) {
0 commit comments