@@ -826,9 +826,6 @@ class Context {
826
826
// / A non-throwing function.
827
827
NonThrowingFunction,
828
828
829
- // / A rethrowing function.
830
- RethrowingFunction,
831
-
832
829
// / A default argument expression.
833
830
DefaultArgument,
834
831
@@ -864,12 +861,27 @@ class Context {
864
861
Optional<AnyFunctionRef> Function;
865
862
bool IsNonExhaustiveCatch = false ;
866
863
bool DiagnoseErrorOnTry = false ;
867
- DeclContext *RethrowsDC = nullptr ;
868
864
InterpolatedStringLiteralExpr *InterpolatedString = nullptr ;
869
865
870
866
explicit Context (Kind kind, Optional<AnyFunctionRef> function = None)
871
867
: TheKind(kind), Function(function) {}
872
868
869
+ public:
870
+ // / Whether this is a function that rethrows.
871
+ bool isRethrows () const {
872
+ if (getKind () != Kind::Handled)
873
+ return false ;
874
+
875
+ if (!Function)
876
+ return false ;
877
+
878
+ auto fn = Function->getAbstractFunctionDecl ();
879
+ if (!fn)
880
+ return false ;
881
+
882
+ return fn->getAttrs ().hasAttribute <RethrowsAttr>();
883
+ }
884
+
873
885
// / Whether this is an autoclosure.
874
886
bool isAutoClosure () const {
875
887
if (!Function)
@@ -882,7 +894,6 @@ class Context {
882
894
return isa<AutoClosureExpr>(closure);
883
895
}
884
896
885
- public:
886
897
static Context getHandled () {
887
898
return Context (Kind::Handled);
888
899
}
@@ -893,12 +904,6 @@ class Context {
893
904
}
894
905
895
906
static Context forFunction (AbstractFunctionDecl *D) {
896
- if (D->getAttrs ().hasAttribute <RethrowsAttr>()) {
897
- Context result (Kind::RethrowingFunction, AnyFunctionRef (D));
898
- result.RethrowsDC = D;
899
- return result;
900
- }
901
-
902
907
// HACK: If the decl is the synthesized getter for a 'lazy' property, then
903
908
// treat the context as a property initializer in order to produce a better
904
909
// diagnostic; the only code we should be diagnosing on is within the
@@ -972,8 +977,7 @@ class Context {
972
977
Kind getKind () const { return TheKind; }
973
978
974
979
bool handlesNothing () const {
975
- return getKind () != Kind::Handled &&
976
- getKind () != Kind::RethrowingFunction;
980
+ return getKind () != Kind::Handled;
977
981
}
978
982
bool handles (ThrowingKind errorKind) const {
979
983
switch (errorKind) {
@@ -982,17 +986,23 @@ class Context {
982
986
983
987
// A call that's rethrowing-only can be handled by 'rethrows'.
984
988
case ThrowingKind::RethrowingOnly:
985
- return ! handlesNothing () ;
989
+ return getKind () == Kind::Handled ;
986
990
987
991
// An operation that always throws can only be handled by an
988
992
// all-handling context.
989
993
case ThrowingKind::Throws:
990
- return getKind () == Kind::Handled;
994
+ return getKind () == Kind::Handled && ! isRethrows () ;
991
995
}
992
996
llvm_unreachable (" bad error kind" );
993
997
}
994
998
995
- DeclContext *getRethrowsDC () const { return RethrowsDC; }
999
+ DeclContext *getRethrowsDC () const {
1000
+ if (!isRethrows ())
1001
+ return nullptr ;
1002
+
1003
+ return Function->getAbstractFunctionDecl ();
1004
+ }
1005
+
996
1006
InterpolatedStringLiteralExpr * getInterpolatedString () const {
997
1007
return InterpolatedString;
998
1008
}
@@ -1098,8 +1108,7 @@ class Context {
1098
1108
// Allow the diagnostic to fire on the 'try' if we don't have
1099
1109
// anything else to say.
1100
1110
if (isTryCovered && !reason.isRethrowsCall () &&
1101
- getKind () == Kind::NonThrowingFunction &&
1102
- !isAutoClosure ()) {
1111
+ !isRethrows () && !isAutoClosure ()) {
1103
1112
DiagnoseErrorOnTry = true ;
1104
1113
return ;
1105
1114
}
@@ -1117,18 +1126,15 @@ class Context {
1117
1126
const PotentialThrowReason &reason) {
1118
1127
switch (getKind ()) {
1119
1128
case Kind::Handled:
1120
- llvm_unreachable (" throw site is handled!" );
1121
-
1122
- // TODO: Doug suggested that we could generate one error per
1123
- // non-throwing function with throw sites within it, possibly with
1124
- // notes for the throw sites.
1129
+ if (isRethrows ()) {
1130
+ diagnoseThrowInLegalContext (Diags, E, isTryCovered, reason,
1131
+ diag::throw_in_rethrows_function,
1132
+ diag::throwing_call_in_rethrows_function,
1133
+ diag::tryless_throwing_call_in_rethrows_function);
1134
+ return ;
1135
+ }
1125
1136
1126
- case Kind::RethrowingFunction:
1127
- diagnoseThrowInLegalContext (Diags, E, isTryCovered, reason,
1128
- diag::throw_in_rethrows_function,
1129
- diag::throwing_call_in_rethrows_function,
1130
- diag::tryless_throwing_call_in_rethrows_function);
1131
- return ;
1137
+ llvm_unreachable (" throw site is handled!" );
1132
1138
1133
1139
case Kind::NonThrowingFunction:
1134
1140
if (IsNonExhaustiveCatch) {
@@ -1186,7 +1192,6 @@ class Context {
1186
1192
void diagnoseUnhandledTry (DiagnosticEngine &Diags, TryExpr *E) {
1187
1193
switch (getKind ()) {
1188
1194
case Kind::Handled:
1189
- case Kind::RethrowingFunction:
1190
1195
llvm_unreachable (" try is handled!" );
1191
1196
1192
1197
case Kind::NonThrowingFunction:
@@ -1471,7 +1476,7 @@ class CheckEffectsCoverage : public EffectsHandlingWalker<CheckEffectsCoverage>
1471
1476
1472
1477
auto savedContext = CurContext;
1473
1478
if (doThrowingKind != ThrowingKind::Throws &&
1474
- CurContext.getKind () == Context::Kind::RethrowingFunction ) {
1479
+ CurContext.isRethrows () ) {
1475
1480
// If this catch clause is reachable at all, it's because a function
1476
1481
// parameter throws. So let's temporarily set our context to Handled so
1477
1482
// the catch body is allowed to throw.
0 commit comments