18
18
#include " TypeChecker.h"
19
19
#include " TypeCheckConcurrency.h"
20
20
#include " TypeCheckEffects.h"
21
+ #include " swift/AST/ASTBridging.h"
21
22
#include " swift/AST/ASTWalker.h"
22
23
#include " swift/AST/DiagnosticsSema.h"
23
24
#include " swift/AST/Effects.h"
@@ -522,9 +523,7 @@ class EffectsHandlingWalker : public ASTWalker {
522
523
ShouldRecurse_t recurse = ShouldRecurse;
523
524
// Skip the implementations of all local declarations... except
524
525
// 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)) {
528
527
if (patternBinding->isAsyncLet ())
529
528
recurse = asImpl ().checkAsyncLet (patternBinding);
530
529
} else if (auto macroExpansionDecl = dyn_cast<MacroExpansionDecl>(D)) {
@@ -1717,10 +1716,6 @@ class ApplyClassifier {
1717
1716
return ShouldRecurse;
1718
1717
}
1719
1718
1720
- ShouldRecurse_t checkIfConfig (IfConfigDecl *D) {
1721
- return ShouldRecurse;
1722
- }
1723
-
1724
1719
ShouldRecurse_t checkForEach (ForEachStmt *S) {
1725
1720
classification.merge (Self.classifyForEach (S));
1726
1721
return ShouldRecurse;
@@ -1832,10 +1827,6 @@ class ApplyClassifier {
1832
1827
return ShouldRecurse;
1833
1828
}
1834
1829
1835
- ShouldRecurse_t checkIfConfig (IfConfigDecl *D) {
1836
- return ShouldRecurse;
1837
- }
1838
-
1839
1830
ShouldRecurse_t checkDoCatch (DoCatchStmt *S) {
1840
1831
return ShouldRecurse;
1841
1832
}
@@ -2719,6 +2710,14 @@ class Context {
2719
2710
2720
2711
};
2721
2712
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
+
2722
2721
// / A class to walk over a local context and validate the correctness
2723
2722
// / of its error coverage.
2724
2723
class CheckEffectsCoverage : public EffectsHandlingWalker <CheckEffectsCoverage> {
@@ -3165,7 +3164,7 @@ class CheckEffectsCoverage : public EffectsHandlingWalker<CheckEffectsCoverage>
3165
3164
3166
3165
S->getBody ()->walk (*this );
3167
3166
3168
- diagnoseNoThrowInDo (S, scope);
3167
+ diagnoseNoThrowInDo (S, scope, S-> getBody ()-> getSourceRange () );
3169
3168
3170
3169
return MaxThrowingKind;
3171
3170
}
@@ -3189,17 +3188,40 @@ class CheckEffectsCoverage : public EffectsHandlingWalker<CheckEffectsCoverage>
3189
3188
3190
3189
S->getBody ()->walk (*this );
3191
3190
3192
- diagnoseNoThrowInDo (S, scope);
3191
+ diagnoseNoThrowInDo (S, scope, S-> getBody ()-> getSourceRange () );
3193
3192
3194
3193
scope.preserveCoverageFromNonExhaustiveCatch ();
3195
3194
return MaxThrowingKind;
3196
3195
}
3197
3196
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
+ ) {
3199
3220
// Warn if nothing threw within the body, unless this is the
3200
3221
// implicit do/catch in a debugger function.
3201
3222
if (!Flags.has (ContextFlags::HasAnyThrowSite) &&
3202
- !scope.wasTopLevelDebuggerFunction ()) {
3223
+ !scope.wasTopLevelDebuggerFunction () &&
3224
+ !inactiveCodeContainsTryOrThrow (bodyRange)) {
3203
3225
Ctx.Diags .diagnose (S->getCatches ().front ()->getStartLoc (),
3204
3226
diag::no_throw_in_do_with_catch);
3205
3227
}
@@ -3318,41 +3340,6 @@ class CheckEffectsCoverage : public EffectsHandlingWalker<CheckEffectsCoverage>
3318
3340
return ShouldNotRecurse;
3319
3341
}
3320
3342
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
-
3356
3343
ShouldRecurse_t checkThrow (ThrowStmt *S) {
3357
3344
if (auto classification = getApplyClassifier ().classifyThrow (S)) {
3358
3345
Flags.set (ContextFlags::HasAnyThrowSite);
0 commit comments