@@ -103,33 +103,71 @@ struct ExpectedFixIt {
103
103
std::string Text;
104
104
};
105
105
106
+ struct DiagLoc {
107
+ std::optional<unsigned > bufferID;
108
+ unsigned line;
109
+ unsigned column;
110
+ SourceLoc sourceLoc;
111
+
112
+ DiagLoc (SourceManager &diagSM, SourceManager &verifierSM,
113
+ SourceLoc initialSourceLoc, bool wantEnd = false )
114
+ : sourceLoc(initialSourceLoc), bufferID(std::nullopt), line(0 ), column(0 )
115
+ {
116
+ if (sourceLoc.isInvalid ())
117
+ return ;
118
+
119
+ // Walk out of generated code for macros in default arguments so that we
120
+ // register diagnostics emitted in them at the call site instead.
121
+ while (true ) {
122
+ bufferID = diagSM.findBufferContainingLoc (sourceLoc);
123
+ ASSERT (bufferID.has_value ());
124
+
125
+ auto generatedInfo = diagSM.getGeneratedSourceInfo (*bufferID);
126
+ if (!generatedInfo || generatedInfo->originalSourceRange .isInvalid ()
127
+ || generatedInfo->kind != GeneratedSourceInfo::DefaultArgument)
128
+ break ;
129
+
130
+ if (wantEnd)
131
+ sourceLoc = generatedInfo->originalSourceRange .getEnd ();
132
+ else
133
+ sourceLoc = generatedInfo->originalSourceRange .getStart ();
134
+
135
+ ASSERT (sourceLoc.isValid ());
136
+ }
137
+
138
+ // If this diagnostic came from a different SourceManager (as can happen
139
+ // while compiling a module interface), translate its SourceLoc to match the
140
+ // verifier's SourceManager.
141
+ if (&diagSM != &verifierSM) {
142
+ sourceLoc = verifierSM.getLocForForeignLoc (sourceLoc, diagSM);
143
+ bufferID = verifierSM.findBufferContainingLoc (sourceLoc);
144
+ }
145
+
146
+ // At this point, `bufferID` is filled in and `sourceLoc` is a location in
147
+ // that buffer.
148
+ if (sourceLoc.isValid ())
149
+ std::tie (line, column) = verifierSM.getLineAndColumnInBuffer (sourceLoc);
150
+ }
151
+ };
152
+
106
153
} // end namespace swift
107
154
108
155
const LineColumnRange &
109
- CapturedFixItInfo::getLineColumnRange (const SourceManager &SM,
110
- unsigned BufferID) const {
156
+ CapturedFixItInfo::getLineColumnRange (SourceManager &SM) const {
111
157
if (LineColRange.StartLine != 0 ) {
112
158
// Already computed.
113
159
return LineColRange;
114
160
}
115
161
116
162
auto SrcRange = FixIt.getRange ();
117
163
118
- std::tie (LineColRange.StartLine , LineColRange.StartCol ) =
119
- SM.getPresumedLineAndColumnForLoc (SrcRange.getStart (), BufferID);
120
-
121
- // We don't have to compute much if the end location is on the same line.
122
- if (SrcRange.getByteLength () == 0 ) {
123
- LineColRange.EndLine = LineColRange.StartLine ;
124
- LineColRange.EndCol = LineColRange.StartCol ;
125
- } else if (SM.extractText (SrcRange, BufferID).find_first_of (" \n\r " ) ==
126
- StringRef::npos) {
127
- LineColRange.EndLine = LineColRange.StartLine ;
128
- LineColRange.EndCol = LineColRange.StartCol + SrcRange.getByteLength ();
129
- } else {
130
- std::tie (LineColRange.EndLine , LineColRange.EndCol ) =
131
- SM.getPresumedLineAndColumnForLoc (SrcRange.getEnd (), BufferID);
132
- }
164
+ DiagLoc startLoc (*diagSM, SM, SrcRange.getStart ());
165
+ LineColRange.StartLine = startLoc.line ;
166
+ LineColRange.StartCol = startLoc.column ;
167
+
168
+ DiagLoc endLoc (*diagSM, SM, SrcRange.getEnd (), /* wantEnd=*/ true );
169
+ LineColRange.EndLine = endLoc.line ;
170
+ LineColRange.EndCol = endLoc.column ;
133
171
134
172
return LineColRange;
135
173
}
@@ -223,13 +261,13 @@ renderEducationalNotes(llvm::SmallVectorImpl<std::string> &EducationalNotes) {
223
261
// / Otherwise return \c CapturedDiagnostics.end() with \c false.
224
262
static std::tuple<std::vector<CapturedDiagnosticInfo>::iterator, bool >
225
263
findDiagnostic (std::vector<CapturedDiagnosticInfo> &CapturedDiagnostics,
226
- const ExpectedDiagnosticInfo &Expected, StringRef BufferName ) {
264
+ const ExpectedDiagnosticInfo &Expected, unsigned BufferID ) {
227
265
auto fallbackI = CapturedDiagnostics.end ();
228
266
229
267
for (auto I = CapturedDiagnostics.begin (), E = CapturedDiagnostics.end ();
230
268
I != E; ++I) {
231
269
// Verify the file and line of the diagnostic.
232
- if (I->Line != Expected.LineNo || I->FileName != BufferName )
270
+ if (I->Line != Expected.LineNo || I->SourceBufferID != BufferID )
233
271
continue ;
234
272
235
273
// If a specific column was expected, verify it.
@@ -363,7 +401,7 @@ bool DiagnosticVerifier::checkForFixIt(
363
401
if (ActualFixIt.getText () != Expected.Text )
364
402
continue ;
365
403
366
- auto &ActualRange = ActualFixIt.getLineColumnRange (SM, BufferID );
404
+ auto &ActualRange = ActualFixIt.getLineColumnRange (SM);
367
405
368
406
if (Expected.Range .StartCol != ActualRange.StartCol ||
369
407
Expected.Range .EndCol != ActualRange.EndCol ||
@@ -394,7 +432,7 @@ DiagnosticVerifier::renderFixits(ArrayRef<CapturedFixItInfo> ActualFixIts,
394
432
interleave (
395
433
ActualFixIts,
396
434
[&](const CapturedFixItInfo &ActualFixIt) {
397
- auto &ActualRange = ActualFixIt.getLineColumnRange (SM, BufferID );
435
+ auto &ActualRange = ActualFixIt.getLineColumnRange (SM);
398
436
OS << " {{" ;
399
437
400
438
if (ActualRange.StartLine != DiagnosticLineNo)
@@ -566,7 +604,6 @@ DiagnosticVerifier::Result DiagnosticVerifier::verifyFile(unsigned BufferID) {
566
604
567
605
const SourceLoc BufferStartLoc = SM.getLocForBufferStart (BufferID);
568
606
StringRef InputFile = SM.getEntireTextForBuffer (BufferID);
569
- StringRef BufferName = SM.getIdentifierForBuffer (BufferID);
570
607
571
608
// Queue up all of the diagnostics, allowing us to sort them and emit them in
572
609
// file order.
@@ -709,7 +746,7 @@ DiagnosticVerifier::Result DiagnosticVerifier::verifyFile(unsigned BufferID) {
709
746
if (PrevExpectedContinuationLine)
710
747
Expected.LineNo = PrevExpectedContinuationLine;
711
748
else
712
- Expected.LineNo = SM.getPresumedLineAndColumnForLoc (
749
+ Expected.LineNo = SM.getLineAndColumnInBuffer (
713
750
BufferStartLoc.getAdvancedLoc (MatchStart.data () -
714
751
InputFile.data ()),
715
752
BufferID)
@@ -888,7 +925,7 @@ DiagnosticVerifier::Result DiagnosticVerifier::verifyFile(unsigned BufferID) {
888
925
889
926
// Check to see if we had this expected diagnostic.
890
927
auto FoundDiagnosticInfo =
891
- findDiagnostic (CapturedDiagnostics, expected, BufferName );
928
+ findDiagnostic (CapturedDiagnostics, expected, BufferID );
892
929
auto FoundDiagnosticIter = std::get<0 >(FoundDiagnosticInfo);
893
930
if (FoundDiagnosticIter == CapturedDiagnostics.end ()) {
894
931
// Diagnostic didn't exist. If this is a 'mayAppear' diagnostic, then
@@ -1078,8 +1115,8 @@ DiagnosticVerifier::Result DiagnosticVerifier::verifyFile(unsigned BufferID) {
1078
1115
auto I = CapturedDiagnostics.begin ();
1079
1116
for (auto E = CapturedDiagnostics.end (); I != E; ++I) {
1080
1117
// Verify the file and line of the diagnostic.
1081
- if (I->Line != expectedDiagIter->LineNo || I->FileName != BufferName ||
1082
- I->Classification != expectedDiagIter->Classification )
1118
+ if (I->Line != expectedDiagIter->LineNo || I->SourceBufferID != BufferID
1119
+ || I->Classification != expectedDiagIter->Classification )
1083
1120
continue ;
1084
1121
1085
1122
// Otherwise, we found it, break out.
@@ -1167,7 +1204,7 @@ DiagnosticVerifier::Result DiagnosticVerifier::verifyFile(unsigned BufferID) {
1167
1204
bool HadUnexpectedDiag = false ;
1168
1205
auto CapturedDiagIter = CapturedDiagnostics.begin ();
1169
1206
while (CapturedDiagIter != CapturedDiagnostics.end ()) {
1170
- if (CapturedDiagIter->FileName != BufferName ) {
1207
+ if (CapturedDiagIter->SourceBufferID != BufferID ) {
1171
1208
++CapturedDiagIter;
1172
1209
continue ;
1173
1210
}
@@ -1241,7 +1278,7 @@ void DiagnosticVerifier::handleDiagnostic(SourceManager &SM,
1241
1278
const DiagnosticInfo &Info) {
1242
1279
SmallVector<CapturedFixItInfo, 2 > fixIts;
1243
1280
for (const auto &fixIt : Info.FixIts ) {
1244
- fixIts.emplace_back (fixIt);
1281
+ fixIts.emplace_back (SM, fixIt);
1245
1282
}
1246
1283
1247
1284
llvm::SmallVector<std::string, 1 > eduNotes;
@@ -1256,40 +1293,39 @@ void DiagnosticVerifier::handleDiagnostic(SourceManager &SM,
1256
1293
Info.FormatArgs );
1257
1294
}
1258
1295
1259
- if (Info.Loc .isValid ()) {
1260
- const auto lineAndColumn = SM.getPresumedLineAndColumnForLoc (Info.Loc );
1261
- const auto fileName = SM.getDisplayNameForLoc (Info.Loc );
1262
- CapturedDiagnostics.emplace_back (message, fileName, Info.Kind , Info.Loc ,
1263
- lineAndColumn.first , lineAndColumn.second ,
1264
- fixIts, eduNotes);
1265
- } else {
1266
- CapturedDiagnostics.emplace_back (message, StringRef (), Info.Kind , Info.Loc ,
1267
- 0 , 0 , fixIts, eduNotes);
1268
- }
1269
-
1270
- // If this diagnostic came from a different SourceManager (as can happen
1271
- // while compiling a module interface), translate its SourceLocs to match the
1272
- // verifier's SourceManager.
1273
- if (&SM != &(this ->SM )) {
1274
- auto &capturedDiag = CapturedDiagnostics.back ();
1275
- auto &correctSM = this ->SM ;
1276
-
1277
- capturedDiag.Loc = correctSM.getLocForForeignLoc (capturedDiag.Loc , SM);
1278
- for (auto &fixIt : capturedDiag.FixIts ) {
1279
- auto newStart =
1280
- correctSM.getLocForForeignLoc (fixIt.getSourceRange ().getStart (), SM);
1281
- auto &mutableRange = fixIt.getSourceRange ();
1282
- mutableRange =
1283
- CharSourceRange (newStart, fixIt.getSourceRange ().getByteLength ());
1284
- }
1285
- }
1296
+ DiagLoc loc (SM, this ->SM , Info.Loc );
1297
+ CapturedDiagnostics.emplace_back (message, loc.bufferID , Info.Kind ,
1298
+ loc.sourceLoc , loc.line , loc.column , fixIts,
1299
+ eduNotes);
1286
1300
}
1287
1301
1288
1302
// / Once all diagnostics have been captured, perform verification.
1289
1303
bool DiagnosticVerifier::finishProcessing () {
1290
1304
DiagnosticVerifier::Result Result = {false , false };
1291
1305
1292
- ArrayRef<unsigned > BufferIDLists[2 ] = { BufferIDs, AdditionalBufferIDs };
1306
+ SmallVector<unsigned , 4 > additionalBufferIDs;
1307
+ for (auto path : AdditionalFilePaths) {
1308
+ auto bufferID = SM.getIDForBufferIdentifier (path);
1309
+ if (!bufferID) {
1310
+ // Still need to scan this file for expectations.
1311
+ auto result = SM.getFileSystem ()->getBufferForFile (path);
1312
+ if (!result) {
1313
+ auto message = SM.GetMessage (
1314
+ SourceLoc (), llvm::SourceMgr::DiagKind::DK_Error,
1315
+ llvm::Twine (" unable to open file in '-verify-additional-file " ) +
1316
+ path + " ': " + result.getError ().message (), {}, {});
1317
+ printDiagnostic (message);
1318
+ Result.HadError |= true ;
1319
+ continue ;
1320
+ }
1321
+ bufferID = SM.addNewSourceBuffer (std::move (result.get ()));
1322
+ }
1323
+ if (bufferID) {
1324
+ additionalBufferIDs.push_back (*bufferID);
1325
+ }
1326
+ }
1327
+
1328
+ ArrayRef<unsigned > BufferIDLists[2 ] = { BufferIDs, additionalBufferIDs };
1293
1329
for (ArrayRef<unsigned > BufferIDList : BufferIDLists)
1294
1330
for (auto &BufferID : BufferIDList) {
1295
1331
DiagnosticVerifier::Result FileResult = verifyFile (BufferID);
0 commit comments