@@ -182,6 +182,11 @@ extern "C" void swift_ASTGen_destroySourceFile(void *sourceFile);
182
182
// / round-trip succeeded, non-zero otherwise.
183
183
extern " C" int swift_ASTGen_roundTripCheck (void *sourceFile);
184
184
185
+ // / Emit parser diagnostics for given source file.. Returns non-zero if any
186
+ // / diagnostics were emitted.
187
+ extern " C" int swift_ASTGen_emitParserDiagnostics (
188
+ void *diagEngine, void *sourceFile
189
+ );
185
190
186
191
// Build AST nodes for the top-level entities in the syntax.
187
192
extern " C" void swift_ASTGen_buildTopLevelASTNodes (void *sourceFile,
@@ -200,9 +205,12 @@ extern "C" void swift_ASTGen_buildTopLevelASTNodes(void *sourceFile,
200
205
// / \endverbatim
201
206
void Parser::parseTopLevelItems (SmallVectorImpl<ASTNode> &items) {
202
207
#if SWIFT_SWIFT_PARSER
208
+ Optional<DiagnosticTransaction> existingParsingTransaction;
203
209
if ((Context.LangOpts .hasFeature (Feature::Macros) ||
204
210
Context.LangOpts .hasFeature (Feature::BuiltinMacros) ||
205
211
Context.LangOpts .hasFeature (Feature::ParserRoundTrip) ||
212
+ Context.LangOpts .hasFeature (Feature::ParserDiagnostics) ||
213
+ Context.LangOpts .hasFeature (Feature::ParserValidation) ||
206
214
Context.LangOpts .hasFeature (Feature::ParserASTGen)) &&
207
215
!SourceMgr.hasIDEInspectionTargetBuffer () &&
208
216
SF.Kind != SourceFileKind::SIL) {
@@ -219,6 +227,18 @@ void Parser::parseTopLevelItems(SmallVectorImpl<ASTNode> &items) {
219
227
swift_ASTGen_destroySourceFile (exportedSourceFile);
220
228
});
221
229
230
+ // If we're supposed to emit diagnostics from the parser, do so now.
231
+ if ((Context.LangOpts .hasFeature (Feature::ParserDiagnostics) ||
232
+ Context.LangOpts .hasFeature (Feature::ParserASTGen)) &&
233
+ swift_ASTGen_emitParserDiagnostics (
234
+ &Context.Diags , SF.exportedSourceFile ) &&
235
+ Context.Diags .hadAnyError () &&
236
+ !Context.LangOpts .hasFeature (Feature::ParserASTGen)) {
237
+ // Errors were emitted, and we're still using the C++ parser, so
238
+ // disable diagnostics from the C++ parser.
239
+ existingParsingTransaction.emplace (Context.Diags );
240
+ }
241
+
222
242
// If we want to do ASTGen, do so now.
223
243
if (Context.LangOpts .hasFeature (Feature::ParserASTGen)) {
224
244
swift_ASTGen_buildTopLevelASTNodes (
@@ -281,16 +301,31 @@ void Parser::parseTopLevelItems(SmallVectorImpl<ASTNode> &items) {
281
301
}
282
302
283
303
#if SWIFT_SWIFT_PARSER
284
- // Perform round-trip checking.
285
- if (Context.LangOpts .hasFeature (Feature::ParserRoundTrip) &&
304
+ if (existingParsingTransaction)
305
+ existingParsingTransaction->abort ();
306
+
307
+ // Perform round-trip and/or validation checking.
308
+ if ((Context.LangOpts .hasFeature (Feature::ParserRoundTrip) ||
309
+ Context.LangOpts .hasFeature (Feature::ParserValidation)) &&
286
310
SF.exportedSourceFile &&
287
- !L->lexingCutOffOffset () &&
288
- swift_ASTGen_roundTripCheck (SF.exportedSourceFile )) {
289
- SourceLoc loc;
290
- if (auto bufferID = SF.getBufferID ()) {
291
- loc = Context.SourceMgr .getLocForBufferStart (*bufferID);
311
+ !L->lexingCutOffOffset ()) {
312
+ if (Context.LangOpts .hasFeature (Feature::ParserRoundTrip) &&
313
+ swift_ASTGen_roundTripCheck (SF.exportedSourceFile )) {
314
+ SourceLoc loc;
315
+ if (auto bufferID = SF.getBufferID ()) {
316
+ loc = Context.SourceMgr .getLocForBufferStart (*bufferID);
317
+ }
318
+ diagnose (loc, diag::parser_round_trip_error);
319
+ } else if (Context.LangOpts .hasFeature (Feature::ParserValidation) &&
320
+ !Context.Diags .hadAnyError () &&
321
+ swift_ASTGen_emitParserDiagnostics (
322
+ &Context.Diags , SF.exportedSourceFile )) {
323
+ SourceLoc loc;
324
+ if (auto bufferID = SF.getBufferID ()) {
325
+ loc = Context.SourceMgr .getLocForBufferStart (*bufferID);
326
+ }
327
+ diagnose (loc, diag::parser_new_parser_errors);
292
328
}
293
- diagnose (loc, diag::parser_round_trip_error);
294
329
}
295
330
#endif
296
331
}
0 commit comments