@@ -279,6 +279,19 @@ namespace swift {
279
279
}
280
280
};
281
281
282
+ namespace detail {
283
+ // / Stores information for an active diagnostic that hasn't been emitted yet.
284
+ // / This includes both "in-flight" diagnostics as well as diagnostics queued
285
+ // / for a transaction.
286
+ struct ActiveDiagnostic {
287
+ Diagnostic Diag;
288
+ SmallVector<DiagnosticInfo, 2 > WrappedDiagnostics;
289
+ SmallVector<std::vector<DiagnosticArgument>, 4 > WrappedDiagnosticArgs;
290
+
291
+ ActiveDiagnostic (Diagnostic diag) : Diag(std::move(diag)) {}
292
+ };
293
+ } // namespace detail
294
+
282
295
// / A diagnostic that has no input arguments, so it is trivially-destructable.
283
296
using ZeroArgDiagnostic = Diag<>;
284
297
@@ -293,33 +306,40 @@ namespace swift {
293
306
friend class DiagnosticEngine ;
294
307
295
308
DiagnosticEngine *Engine;
309
+ unsigned Idx;
296
310
bool IsActive;
297
311
298
312
// / Create a new in-flight diagnostic.
299
313
// /
300
314
// / This constructor is only available to the DiagnosticEngine.
301
- InFlightDiagnostic (DiagnosticEngine &Engine)
302
- : Engine(&Engine), IsActive(true ) { }
303
-
315
+ InFlightDiagnostic (DiagnosticEngine &Engine, unsigned idx )
316
+ : Engine(&Engine), Idx(idx), IsActive(true ) {}
317
+
304
318
InFlightDiagnostic (const InFlightDiagnostic &) = delete ;
305
319
InFlightDiagnostic &operator =(const InFlightDiagnostic &) = delete ;
306
320
InFlightDiagnostic &operator =(InFlightDiagnostic &&) = delete ;
307
321
322
+ // / Retrieve the underlying active diagnostic information.
323
+ detail::ActiveDiagnostic &getActiveDiag () const ;
324
+
325
+ // / Retrieve the underlying diagnostic.
326
+ Diagnostic &getDiag () const { return getActiveDiag ().Diag ; }
327
+
308
328
public:
309
329
// / Create an active but unattached in-flight diagnostic.
310
330
// /
311
331
// / The resulting diagnostic can be used as a dummy, accepting the
312
332
// / syntax to add additional information to a diagnostic without
313
333
// / actually emitting a diagnostic.
314
- InFlightDiagnostic () : Engine(0 ), IsActive(true ) { }
315
-
334
+ InFlightDiagnostic () : Engine(0 ), Idx( 0 ), IsActive(true ) {}
335
+
316
336
// / Transfer an in-flight diagnostic to a new object, which is
317
337
// / typically used when returning in-flight diagnostics.
318
338
InFlightDiagnostic (InFlightDiagnostic &&Other)
319
- : Engine(Other.Engine), IsActive(Other.IsActive) {
339
+ : Engine(Other.Engine), Idx(Other.Idx ), IsActive(Other.IsActive) {
320
340
Other.IsActive = false ;
321
341
}
322
-
342
+
323
343
~InFlightDiagnostic () {
324
344
if (IsActive)
325
345
flush ();
@@ -784,16 +804,12 @@ namespace swift {
784
804
// / Tracks diagnostic behaviors and state
785
805
DiagnosticState state;
786
806
787
- // / The currently active diagnostic, if there is one.
788
- std::optional<Diagnostic> ActiveDiagnostic;
789
-
790
- // / Diagnostics wrapped by ActiveDiagnostic, if any.
791
- SmallVector<DiagnosticInfo, 2 > WrappedDiagnostics;
792
- SmallVector<std::vector<DiagnosticArgument>, 4 > WrappedDiagnosticArgs;
807
+ // / The currently active diagnostics.
808
+ SmallVector<detail::ActiveDiagnostic, 4 > ActiveDiagnostics;
793
809
794
810
// / All diagnostics that have are no longer active but have not yet
795
811
// / been emitted due to an open transaction.
796
- SmallVector<Diagnostic , 4 > TentativeDiagnostics;
812
+ SmallVector<detail::ActiveDiagnostic , 4 > TentativeDiagnostics;
797
813
798
814
llvm::BumpPtrAllocator TransactionAllocator;
799
815
// / A set of all strings involved in current transactional chain.
@@ -816,6 +832,9 @@ namespace swift {
816
832
// / emitted once all transactions have closed.
817
833
unsigned TransactionCount = 0 ;
818
834
835
+ // / The number of currently in-flight diagnostics.
836
+ unsigned NumActiveDiags = 0 ;
837
+
819
838
// / For batch mode, use this to know where to output a diagnostic from a
820
839
// / non-primary file. It's any location in the buffer of the current primary
821
840
// / input being compiled.
@@ -851,7 +870,7 @@ namespace swift {
851
870
852
871
public:
853
872
explicit DiagnosticEngine (SourceManager &SourceMgr)
854
- : SourceMgr(SourceMgr), ActiveDiagnostic (),
873
+ : SourceMgr(SourceMgr), ActiveDiagnostics (),
855
874
TransactionStrings(TransactionAllocator),
856
875
DiagnosticStringsSaver(DiagnosticStringsAllocator) {}
857
876
@@ -870,6 +889,7 @@ namespace swift {
870
889
}
871
890
872
891
void flushConsumers () {
892
+ ASSERT (NumActiveDiags == 0 && " Expected in-flight diags to be flushed" );
873
893
for (auto consumer : Consumers)
874
894
consumer->flush ();
875
895
}
@@ -1001,10 +1021,9 @@ namespace swift {
1001
1021
// / \returns An in-flight diagnostic, to which additional information can
1002
1022
// / be attached.
1003
1023
InFlightDiagnostic diagnose (SourceLoc Loc, const Diagnostic &D) {
1004
- assert (!ActiveDiagnostic && " Already have an active diagnostic" );
1005
- ActiveDiagnostic = D;
1006
- ActiveDiagnostic->setLoc (Loc);
1007
- return InFlightDiagnostic (*this );
1024
+ auto IFD = beginDiagnostic (D);
1025
+ getActiveDiagnostic (IFD).Diag .setLoc (Loc);
1026
+ return IFD;
1008
1027
}
1009
1028
1010
1029
// / Emit a diagnostic with the given set of diagnostic arguments.
@@ -1080,10 +1099,9 @@ namespace swift {
1080
1099
// / \returns An in-flight diagnostic, to which additional information can
1081
1100
// / be attached.
1082
1101
InFlightDiagnostic diagnose (const Decl *decl, const Diagnostic &diag) {
1083
- assert (!ActiveDiagnostic && " Already have an active diagnostic" );
1084
- ActiveDiagnostic = diag;
1085
- ActiveDiagnostic->setDecl (decl);
1086
- return InFlightDiagnostic (*this );
1102
+ auto IFD = beginDiagnostic (diag);
1103
+ getActiveDiagnostic (IFD).Diag .setDecl (decl);
1104
+ return IFD;
1087
1105
}
1088
1106
1089
1107
// / Emit a diagnostic with the given set of diagnostic arguments.
@@ -1137,16 +1155,21 @@ namespace swift {
1137
1155
DiagnosticFormatOptions FormatOpts = DiagnosticFormatOptions());
1138
1156
1139
1157
private:
1158
+ // / Begins a new in-flight diagnostic.
1159
+ InFlightDiagnostic beginDiagnostic (const Diagnostic &D);
1160
+
1161
+ // / Ends an in-flight diagnostic. Once all in-flight diagnostics have ended,
1162
+ // / they will either be emitted, or captured by an open transaction.
1163
+ void endDiagnostic (const InFlightDiagnostic &D);
1164
+
1140
1165
// / Called when tentative diagnostic is about to be flushed,
1141
1166
// / to apply any required transformations e.g. copy string arguments
1142
1167
// / to extend their lifetime.
1143
1168
void onTentativeDiagnosticFlush (Diagnostic &diagnostic);
1144
1169
1145
- // / Flush the active diagnostic.
1146
- void flushActiveDiagnostic ();
1147
-
1148
- // / Retrieve the active diagnostic.
1149
- Diagnostic &getActiveDiagnostic () { return *ActiveDiagnostic; }
1170
+ // / Retrieve the stored active diagnostic for a given InFlightDiagnostic.
1171
+ detail::ActiveDiagnostic &
1172
+ getActiveDiagnostic (const InFlightDiagnostic &diag);
1150
1173
1151
1174
// / Generate DiagnosticInfo for a Diagnostic to be passed to consumers.
1152
1175
std::optional<DiagnosticInfo>
@@ -1162,7 +1185,7 @@ namespace swift {
1162
1185
1163
1186
// / Handle a new diagnostic, which will either be emitted, or added to an
1164
1187
// / active transaction.
1165
- void handleDiagnostic (Diagnostic &&diag);
1188
+ void handleDiagnostic (detail::ActiveDiagnostic &&diag);
1166
1189
1167
1190
// / Clear any tentative diagnostics.
1168
1191
void clearTentativeDiagnostics ();
@@ -1291,12 +1314,12 @@ namespace swift {
1291
1314
}
1292
1315
1293
1316
bool hasErrors () const {
1294
- ArrayRef<Diagnostic > diagnostics (Engine. TentativeDiagnostics . begin () +
1295
- PrevDiagnostics,
1296
- Engine.TentativeDiagnostics .end ());
1317
+ ArrayRef<detail::ActiveDiagnostic > diagnostics (
1318
+ Engine. TentativeDiagnostics . begin () + PrevDiagnostics,
1319
+ Engine.TentativeDiagnostics .end ());
1297
1320
1298
1321
for (auto &diagnostic : diagnostics) {
1299
- auto behavior = Engine.state .determineBehavior (diagnostic);
1322
+ auto behavior = Engine.state .determineBehavior (diagnostic. Diag );
1300
1323
if (behavior == DiagnosticBehavior::Fatal ||
1301
1324
behavior == DiagnosticBehavior::Error)
1302
1325
return true ;
@@ -1361,14 +1384,14 @@ namespace swift {
1361
1384
1362
1385
// The first diagnostic is assumed to be the parent. If this is not an
1363
1386
// error or warning, we'll assert later when trying to add children.
1364
- Diagnostic &parent = Engine.TentativeDiagnostics [PrevDiagnostics];
1387
+ Diagnostic &parent = Engine.TentativeDiagnostics [PrevDiagnostics]. Diag ;
1365
1388
1366
1389
// Associate the children with the parent.
1367
1390
for (auto diag =
1368
1391
Engine.TentativeDiagnostics .begin () + PrevDiagnostics + 1 ;
1369
1392
diag != Engine.TentativeDiagnostics .end (); ++diag) {
1370
- diag->setIsChildNote (true );
1371
- parent.addChildNote (std::move (* diag));
1393
+ diag->Diag . setIsChildNote (true );
1394
+ parent.addChildNote (std::move (diag-> Diag ));
1372
1395
}
1373
1396
1374
1397
// Erase the children, they'll be emitted alongside their parent.
0 commit comments