1818#include " TypeChecker.h"
1919#include " TypeCheckConcurrency.h"
2020#include " TypeCheckEffects.h"
21+ #include " swift/AST/ASTBridging.h"
2122#include " swift/AST/ASTWalker.h"
2223#include " swift/AST/DiagnosticsSema.h"
2324#include " swift/AST/Effects.h"
@@ -522,9 +523,7 @@ class EffectsHandlingWalker : public ASTWalker {
522523 ShouldRecurse_t recurse = ShouldRecurse;
523524 // Skip the implementations of all local declarations... except
524525 // PBD. We should really just have a PatternBindingStmt.
525- if (auto ic = dyn_cast<IfConfigDecl>(D)) {
526- recurse = asImpl ().checkIfConfig (ic);
527- } else if (auto patternBinding = dyn_cast<PatternBindingDecl>(D)) {
526+ if (auto patternBinding = dyn_cast<PatternBindingDecl>(D)) {
528527 if (patternBinding->isAsyncLet ())
529528 recurse = asImpl ().checkAsyncLet (patternBinding);
530529 } else if (auto macroExpansionDecl = dyn_cast<MacroExpansionDecl>(D)) {
@@ -1717,10 +1716,6 @@ class ApplyClassifier {
17171716 return ShouldRecurse;
17181717 }
17191718
1720- ShouldRecurse_t checkIfConfig (IfConfigDecl *D) {
1721- return ShouldRecurse;
1722- }
1723-
17241719 ShouldRecurse_t checkForEach (ForEachStmt *S) {
17251720 classification.merge (Self.classifyForEach (S));
17261721 return ShouldRecurse;
@@ -1832,10 +1827,6 @@ class ApplyClassifier {
18321827 return ShouldRecurse;
18331828 }
18341829
1835- ShouldRecurse_t checkIfConfig (IfConfigDecl *D) {
1836- return ShouldRecurse;
1837- }
1838-
18391830 ShouldRecurse_t checkDoCatch (DoCatchStmt *S) {
18401831 return ShouldRecurse;
18411832 }
@@ -2719,6 +2710,14 @@ class Context {
27192710
27202711};
27212712
2713+ // / ASTGen helper function to look for a "try" or "throw" in inactive code
2714+ // / within the given source file.
2715+ extern " C" bool swift_ASTGen_inactiveCodeContainsTryOrThrow (
2716+ BridgedASTContext ctx,
2717+ BridgedStringRef sourceFileBuffer,
2718+ BridgedStringRef searchRange
2719+ );
2720+
27222721// / A class to walk over a local context and validate the correctness
27232722// / of its error coverage.
27242723class CheckEffectsCoverage : public EffectsHandlingWalker <CheckEffectsCoverage> {
@@ -3165,7 +3164,7 @@ class CheckEffectsCoverage : public EffectsHandlingWalker<CheckEffectsCoverage>
31653164
31663165 S->getBody ()->walk (*this );
31673166
3168- diagnoseNoThrowInDo (S, scope);
3167+ diagnoseNoThrowInDo (S, scope, S-> getBody ()-> getSourceRange () );
31693168
31703169 return MaxThrowingKind;
31713170 }
@@ -3189,17 +3188,40 @@ class CheckEffectsCoverage : public EffectsHandlingWalker<CheckEffectsCoverage>
31893188
31903189 S->getBody ()->walk (*this );
31913190
3192- diagnoseNoThrowInDo (S, scope);
3191+ diagnoseNoThrowInDo (S, scope, S-> getBody ()-> getSourceRange () );
31933192
31943193 scope.preserveCoverageFromNonExhaustiveCatch ();
31953194 return MaxThrowingKind;
31963195 }
31973196
3198- void diagnoseNoThrowInDo (DoCatchStmt *S, ContextScope &scope) {
3197+ // / Determine whether the inactive code within the given body range
3198+ // / contains a "try" or a "throw".
3199+ bool inactiveCodeContainsTryOrThrow (SourceRange bodyRange) {
3200+ #if SWIFT_BUILD_SWIFT_SYNTAX
3201+ SourceManager &sourceMgr = Ctx.SourceMgr ;
3202+ auto bufferID = sourceMgr.findBufferContainingLoc (bodyRange.Start );
3203+ StringRef sourceFileText = sourceMgr.getEntireTextForBuffer (bufferID);
3204+
3205+ // Extract the search text from that buffer.
3206+ auto searchTextCharRange = Lexer::getCharSourceRangeFromSourceRange (
3207+ sourceMgr, bodyRange);
3208+ StringRef searchText = sourceMgr.extractText (searchTextCharRange, bufferID);
3209+
3210+ return swift_ASTGen_inactiveCodeContainsTryOrThrow (
3211+ Ctx, sourceFileText, searchText);
3212+ #else
3213+ return false ;
3214+ #endif
3215+ }
3216+
3217+ void diagnoseNoThrowInDo (
3218+ DoCatchStmt *S, ContextScope &scope, SourceRange bodyRange
3219+ ) {
31993220 // Warn if nothing threw within the body, unless this is the
32003221 // implicit do/catch in a debugger function.
32013222 if (!Flags.has (ContextFlags::HasAnyThrowSite) &&
3202- !scope.wasTopLevelDebuggerFunction ()) {
3223+ !scope.wasTopLevelDebuggerFunction () &&
3224+ !inactiveCodeContainsTryOrThrow (bodyRange)) {
32033225 Ctx.Diags .diagnose (S->getCatches ().front ()->getStartLoc (),
32043226 diag::no_throw_in_do_with_catch);
32053227 }
@@ -3318,41 +3340,6 @@ class CheckEffectsCoverage : public EffectsHandlingWalker<CheckEffectsCoverage>
33183340 return ShouldNotRecurse;
33193341 }
33203342
3321- ShouldRecurse_t checkIfConfig (IfConfigDecl *ICD) {
3322- // Check the inactive regions of a #if block to disable warnings that may
3323- // be due to platform specific code.
3324- struct ConservativeThrowChecker : public ASTWalker {
3325- CheckEffectsCoverage &CEC;
3326- ConservativeThrowChecker (CheckEffectsCoverage &CEC) : CEC(CEC) {}
3327-
3328- MacroWalking getMacroWalkingBehavior () const override {
3329- return MacroWalking::Arguments;
3330- }
3331-
3332- PostWalkResult<Expr *> walkToExprPost (Expr *E) override {
3333- if (isa<TryExpr>(E))
3334- CEC.Flags .set (ContextFlags::HasAnyThrowSite);
3335- return Action::Continue (E);
3336- }
3337-
3338- PostWalkResult<Stmt *> walkToStmtPost (Stmt *S) override {
3339- if (isa<ThrowStmt>(S))
3340- CEC.Flags .set (ContextFlags::HasAnyThrowSite);
3341-
3342- return Action::Continue (S);
3343- }
3344- };
3345-
3346- for (auto &clause : ICD->getClauses ()) {
3347- // Active clauses are handled by the normal AST walk.
3348- if (clause.isActive ) continue ;
3349-
3350- for (auto elt : clause.Elements )
3351- elt.walk (ConservativeThrowChecker (*this ));
3352- }
3353- return ShouldRecurse;
3354- }
3355-
33563343 ShouldRecurse_t checkThrow (ThrowStmt *S) {
33573344 if (auto classification = getApplyClassifier ().classifyThrow (S)) {
33583345 Flags.set (ContextFlags::HasAnyThrowSite);
0 commit comments