@@ -3850,7 +3850,20 @@ class SingleValueStmtUsageChecker final : public ASTWalker {
3850
3850
llvm::DenseSet<SingleValueStmtExpr *> ValidSingleValueStmtExprs;
3851
3851
3852
3852
public:
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
+ }
3854
3867
3855
3868
private:
3856
3869
// / Mark a given expression as a valid position for a SingleValueStmtExpr.
@@ -3862,8 +3875,23 @@ class SingleValueStmtUsageChecker final : public ASTWalker {
3862
3875
ValidSingleValueStmtExprs.insert (SVE);
3863
3876
}
3864
3877
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
+
3865
3893
MacroWalking getMacroWalkingBehavior () const override {
3866
- return MacroWalking::Expansion ;
3894
+ return MacroWalking::ArgumentsAndExpansion ;
3867
3895
}
3868
3896
3869
3897
AssignExpr *findAssignment (Expr *E) const {
@@ -3989,28 +4017,33 @@ class SingleValueStmtUsageChecker final : public ASTWalker {
3989
4017
if (auto *PBD = dyn_cast<PatternBindingDecl>(D)) {
3990
4018
for (auto idx : range (PBD->getNumPatternEntries ()))
3991
4019
markValidSingleValueStmt (PBD->getInit (idx));
4020
+
4021
+ return Action::Continue ();
3992
4022
}
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 ();
4001
4026
}
4002
4027
};
4003
4028
} // end anonymous namespace
4004
4029
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
+
4005
4040
// / Apply the warnings managed by VarDeclUsageChecker to the top level
4006
4041
// / code declarations that haven't been checked yet.
4007
4042
void swift::
4008
4043
performTopLevelDeclDiagnostics (TopLevelCodeDecl *TLCD) {
4009
4044
auto &ctx = TLCD->getDeclContext ()->getASTContext ();
4010
4045
VarDeclUsageChecker checker (TLCD, ctx.Diags );
4011
4046
TLCD->walk (checker);
4012
- SingleValueStmtUsageChecker sveChecker (ctx);
4013
- TLCD->walk (sveChecker);
4014
4047
}
4015
4048
4016
4049
// / Perform diagnostics for func/init/deinit declarations.
@@ -4026,10 +4059,6 @@ void swift::performAbstractFuncDeclDiagnostics(AbstractFunctionDecl *AFD) {
4026
4059
auto &ctx = AFD->getDeclContext ()->getASTContext ();
4027
4060
VarDeclUsageChecker checker (AFD, ctx.Diags );
4028
4061
AFD->walk (checker);
4029
-
4030
- // Do a similar walk to check for out of place SingleValueStmtExprs.
4031
- SingleValueStmtUsageChecker sveChecker (ctx);
4032
- AFD->walk (sveChecker);
4033
4062
}
4034
4063
4035
4064
auto *body = AFD->getBody ();
@@ -5864,10 +5893,10 @@ diagnoseDictionaryLiteralDuplicateKeyEntries(const Expr *E,
5864
5893
// ===----------------------------------------------------------------------===//
5865
5894
5866
5895
// / 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 ) {
5871
5900
auto &ctx = DC->getASTContext ();
5872
5901
TypeChecker::diagnoseSelfAssignment (E);
5873
5902
diagSyntacticUseRestrictions (E, DC, isExprStmt);
@@ -5886,6 +5915,8 @@ void swift::performSyntacticExprDiagnostics(const Expr *E,
5886
5915
diagnoseConstantArgumentRequirement (E, DC);
5887
5916
diagUnqualifiedAccessToMethodNamedSelf (E, DC);
5888
5917
diagnoseDictionaryLiteralDuplicateKeyEntries (E, DC);
5918
+ if (!disableOutOfPlaceExprChecking)
5919
+ diagnoseOutOfPlaceExprs (ctx, const_cast <Expr *>(E), contextualPurpose);
5889
5920
}
5890
5921
5891
5922
void swift::performStmtDiagnostics (const Stmt *S, DeclContext *DC) {
0 commit comments