@@ -136,41 +136,57 @@ class NullDiagnosticConsumer : public DiagnosticConsumer {
136
136
// / current file.
137
137
class FileSpecificDiagnosticConsumer : public DiagnosticConsumer {
138
138
public:
139
+ class Subconsumer ;
140
+
141
+ // / Given a vector of subconsumers, return the most specific DiagnosticConsumer for that vector.
142
+ // / That will be a FileSpecificDiagnosticConsumer if the vector has > 1 subconsumer,
143
+ // / the subconsumer itself if the vector has just one, or a null pointer if there are no subconsumers.
144
+ // / Takes ownership of the DiagnosticConsumers specified in \p subconsumers.
145
+ static std::unique_ptr<DiagnosticConsumer> consolidateSubconsumers (SmallVectorImpl<Subconsumer> &subconsumers);
146
+
139
147
// / A diagnostic consumer, along with the name of the buffer that it should
140
148
// / be associated with.
141
149
class Subconsumer {
142
- public:
143
- // / The name of the buffer that a consumer should
150
+ friend std::unique_ptr<DiagnosticConsumer> FileSpecificDiagnosticConsumer::consolidateSubconsumers (SmallVectorImpl<Subconsumer> &subconsumers);
151
+
152
+ // / The name of the input file that a consumer and diagnostics should
144
153
// / be associated with. An empty string means that a consumer is not
145
154
// / associated with any particular buffer, and should only receive
146
155
// / diagnostics that are not in any of the other consumers' files.
147
- std::string bufferName;
148
-
156
+ std::string inputFileName;
157
+
158
+ // / The consumer (if any) for diagnostics associated with the inputFileName.
149
159
// / A null pointer for the DiagnosticConsumer means that diagnostics for
150
160
// / this file should not be emitted.
151
161
std::unique_ptr<DiagnosticConsumer> consumer;
152
-
162
+
153
163
// Has this subconsumer ever handled a diagnostic that is an error?
154
- bool handledError = false ;
164
+ bool hasAnErrorBeenConsumed = false ;
155
165
156
- Subconsumer (std::string bufferName,
166
+
167
+ public:
168
+ std::string getInputFileName () const { return inputFileName; }
169
+
170
+ DiagnosticConsumer *getConsumer () const { return consumer.get (); }
171
+
172
+ Subconsumer (std::string inputFileName,
157
173
std::unique_ptr<DiagnosticConsumer> consumer)
158
- : bufferName(bufferName ), consumer(std::move(consumer)) {}
174
+ : inputFileName(inputFileName ), consumer(std::move(consumer)) {}
159
175
160
176
void handleDiagnostic (SourceManager &SM, SourceLoc Loc,
161
177
DiagnosticKind Kind,
162
178
StringRef FormatString,
163
179
ArrayRef<DiagnosticArgument> FormatArgs,
164
180
const DiagnosticInfo &Info) {
165
- if (!consumer )
181
+ if (!getConsumer () )
166
182
return ; // Suppress non-primary diagnostic in batch mode.
167
- handledError |= Kind == DiagnosticKind::Error;
168
- consumer. get ()->handleDiagnostic (SM, Loc, Kind, FormatString, FormatArgs, Info);
183
+ hasAnErrorBeenConsumed |= Kind == DiagnosticKind::Error;
184
+ getConsumer ()->handleDiagnostic (SM, Loc, Kind, FormatString, FormatArgs, Info);
169
185
}
170
186
171
187
void informDriverOfIncompleteBatchModeCompilation () {
172
- if (!handledError && consumer )
173
- consumer. get ()->informDriverOfIncompleteBatchModeCompilation ();
188
+ if (!hasAnErrorBeenConsumed && getConsumer () )
189
+ getConsumer ()->informDriverOfIncompleteBatchModeCompilation ();
174
190
}
175
191
};
176
192
@@ -181,19 +197,46 @@ class FileSpecificDiagnosticConsumer : public DiagnosticConsumer {
181
197
public:
182
198
// The commented-out consts are there because the data does not change
183
199
// but the swap method gets called on this structure.
184
- struct ConsumerSpecificInformation {
200
+ class ConsumerSpecificInformation {
201
+ private:
202
+ // / The range of SourceLoc's for which diagnostics should be directed to
203
+ // / this subconsumer.
185
204
/* const*/ CharSourceRange range;
186
-
187
- // / Index into Subconsumers vector.
188
- unsigned subconsumerIndex;
189
205
206
+ // / Index into Subconsumers vector for this subconsumer.
207
+ /* const*/ unsigned subconsumerIndex;
208
+
209
+ public:
190
210
ConsumerSpecificInformation (const CharSourceRange range,
191
211
unsigned subconsumerIndex)
192
- : range(range), subconsumerIndex(subconsumerIndex) {}
193
-
212
+ : range(range), subconsumerIndex(subconsumerIndex) {}
213
+
194
214
Subconsumer &subconsumer (FileSpecificDiagnosticConsumer &c) const {
195
215
return c.Subconsumers [subconsumerIndex];
196
216
}
217
+
218
+ // / Compare according to range:
219
+ bool operator < (const ConsumerSpecificInformation &right) const {
220
+ auto compare = std::less<const char *>();
221
+ return compare (getRawLoc ( range.getEnd ()).getPointer (),
222
+ getRawLoc (right.range .getEnd ()).getPointer ());
223
+ }
224
+
225
+ // / Overlaps by range:
226
+ bool overlaps (const ConsumerSpecificInformation &other) const {
227
+ return range.overlaps (other.range );
228
+ }
229
+
230
+ // / Does my range end after \p loc?
231
+ bool endsAfter (const SourceLoc loc) const {
232
+ auto compare = std::less<const char *>();
233
+ return compare (getRawLoc (range.getEnd ()).getPointer (),
234
+ getRawLoc (loc).getPointer ());
235
+ }
236
+
237
+ bool contains (const SourceLoc loc) const {
238
+ return range.contains (loc);
239
+ }
197
240
};
198
241
199
242
private:
@@ -219,15 +262,19 @@ class FileSpecificDiagnosticConsumer : public DiagnosticConsumer {
219
262
ConsumerSpecificInfoForSubsequentNotes = None;
220
263
221
264
bool HasAnErrorBeenConsumed = false ;
222
-
223
- public:
265
+
266
+
224
267
// / Takes ownership of the DiagnosticConsumers specified in \p consumers.
225
268
// /
226
269
// / There must not be two consumers for the same file (i.e., having the same
227
270
// / buffer name).
228
271
explicit FileSpecificDiagnosticConsumer (
229
- SmallVectorImpl<Subconsumer> &consumers);
272
+ SmallVectorImpl<Subconsumer> &consumers);
230
273
274
+ public:
275
+
276
+
277
+
231
278
void handleDiagnostic (SourceManager &SM, SourceLoc Loc,
232
279
DiagnosticKind Kind,
233
280
StringRef FormatString,
0 commit comments