@@ -115,6 +115,7 @@ namespace swift {
115115 VersionTuple,
116116 LayoutConstraint,
117117 ActorIsolation,
118+ Diagnostic
118119 };
119120
120121 namespace diag {
@@ -146,6 +147,7 @@ namespace swift {
146147 llvm::VersionTuple VersionVal;
147148 LayoutConstraint LayoutConstraintVal;
148149 ActorIsolation ActorIsolationVal;
150+ DiagnosticInfo *DiagnosticVal;
149151 };
150152
151153 public:
@@ -243,6 +245,11 @@ namespace swift {
243245 ActorIsolationVal(AI) {
244246 }
245247
248+ DiagnosticArgument (DiagnosticInfo *D)
249+ : Kind(DiagnosticArgumentKind::Diagnostic),
250+ DiagnosticVal(D) {
251+ }
252+
246253 // / Initializes a diagnostic argument using the underlying type of the
247254 // / given enum.
248255 template <
@@ -343,6 +350,11 @@ namespace swift {
343350 assert (Kind == DiagnosticArgumentKind::ActorIsolation);
344351 return ActorIsolationVal;
345352 }
353+
354+ DiagnosticInfo *getAsDiagnostic () const {
355+ assert (Kind == DiagnosticArgumentKind::Diagnostic);
356+ return DiagnosticVal;
357+ }
346358 };
347359
348360 // / Describes the current behavior to take with a diagnostic.
@@ -410,6 +422,7 @@ namespace swift {
410422 DiagnosticBehavior BehaviorLimit = DiagnosticBehavior::Unspecified;
411423
412424 friend DiagnosticEngine;
425+ friend class InFlightDiagnostic ;
413426
414427 public:
415428 // All constructors are intentionally implicit.
@@ -515,6 +528,42 @@ namespace swift {
515528 // / emitted as a warning, but a note will still be emitted as a note.
516529 InFlightDiagnostic &limitBehavior (DiagnosticBehavior limit);
517530
531+ // / Wraps this diagnostic in another diagnostic. That is, \p wrapper will be
532+ // / emitted in place of the diagnostic that otherwise would have been
533+ // / emitted.
534+ // /
535+ // / The first argument of \p wrapper must be of type 'Diagnostic *'.
536+ // /
537+ // / The emitted diagnostic will have:
538+ // /
539+ // / \li The ID, message, and behavior of \c wrapper.
540+ // / \li The arguments of \c wrapper, with the last argument replaced by the
541+ // / diagnostic currently in \c *this.
542+ // / \li The location, ranges, decl, fix-its, and behavior limit of the
543+ // / diagnostic currently in \c *this.
544+ InFlightDiagnostic &wrapIn (const Diagnostic &wrapper);
545+
546+ // / Wraps this diagnostic in another diagnostic. That is, \p ID and
547+ // / \p VArgs will be emitted in place of the diagnostic that otherwise would
548+ // / have been emitted.
549+ // /
550+ // / The first argument of \p ID must be of type 'Diagnostic *'.
551+ // /
552+ // / The emitted diagnostic will have:
553+ // /
554+ // / \li The ID, message, and behavior of \c ID.
555+ // / \li The arguments of \c VArgs, with an argument appended for the
556+ // / diagnostic currently in \c *this.
557+ // / \li The location, ranges, decl, fix-its, and behavior limit of the
558+ // / diagnostic currently in \c *this.
559+ template <typename ...ArgTypes>
560+ InFlightDiagnostic &
561+ wrapIn (Diag<DiagnosticInfo *, ArgTypes...> ID,
562+ typename detail::PassArgument<ArgTypes>::type... VArgs) {
563+ Diagnostic wrapper{ID, nullptr , std::move (VArgs)...};
564+ return wrapIn (wrapper);
565+ }
566+
518567 // / Add a token-based range to the currently-active diagnostic.
519568 InFlightDiagnostic &highlight (SourceRange R);
520569
@@ -678,6 +727,16 @@ namespace swift {
678727 ignoredDiagnostics[(unsigned )id] = ignored;
679728 }
680729
730+ void swap (DiagnosticState &other) {
731+ std::swap (showDiagnosticsAfterFatalError, other.showDiagnosticsAfterFatalError );
732+ std::swap (suppressWarnings, other.suppressWarnings );
733+ std::swap (warningsAsErrors, other.warningsAsErrors );
734+ std::swap (fatalErrorOccurred, other.fatalErrorOccurred );
735+ std::swap (anyErrorOccurred, other.anyErrorOccurred );
736+ std::swap (previousBehavior, other.previousBehavior );
737+ std::swap (ignoredDiagnostics, other.ignoredDiagnostics );
738+ }
739+
681740 private:
682741 // Make the state movable only
683742 DiagnosticState (const DiagnosticState &) = delete ;
@@ -706,6 +765,10 @@ namespace swift {
706765 // / The currently active diagnostic, if there is one.
707766 Optional<Diagnostic> ActiveDiagnostic;
708767
768+ // / Diagnostics wrapped by ActiveDiagnostic, if any.
769+ SmallVector<DiagnosticInfo, 2 > WrappedDiagnostics;
770+ SmallVector<std::vector<DiagnosticArgument>, 4 > WrappedDiagnosticArgs;
771+
709772 // / All diagnostics that have are no longer active but have not yet
710773 // / been emitted due to an open transaction.
711774 SmallVector<Diagnostic, 4 > TentativeDiagnostics;
0 commit comments