@@ -103,33 +103,71 @@ struct ExpectedFixIt {
103103 std::string Text;
104104};
105105
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+
106153} // end namespace swift
107154
108155const LineColumnRange &
109- CapturedFixItInfo::getLineColumnRange (const SourceManager &SM,
110- unsigned BufferID) const {
156+ CapturedFixItInfo::getLineColumnRange (SourceManager &SM) const {
111157 if (LineColRange.StartLine != 0 ) {
112158 // Already computed.
113159 return LineColRange;
114160 }
115161
116162 auto SrcRange = FixIt.getRange ();
117163
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 ;
133171
134172 return LineColRange;
135173}
@@ -223,13 +261,13 @@ renderEducationalNotes(llvm::SmallVectorImpl<std::string> &EducationalNotes) {
223261// / Otherwise return \c CapturedDiagnostics.end() with \c false.
224262static std::tuple<std::vector<CapturedDiagnosticInfo>::iterator, bool >
225263findDiagnostic (std::vector<CapturedDiagnosticInfo> &CapturedDiagnostics,
226- const ExpectedDiagnosticInfo &Expected, StringRef BufferName ) {
264+ const ExpectedDiagnosticInfo &Expected, unsigned BufferID ) {
227265 auto fallbackI = CapturedDiagnostics.end ();
228266
229267 for (auto I = CapturedDiagnostics.begin (), E = CapturedDiagnostics.end ();
230268 I != E; ++I) {
231269 // 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 )
233271 continue ;
234272
235273 // If a specific column was expected, verify it.
@@ -363,7 +401,7 @@ bool DiagnosticVerifier::checkForFixIt(
363401 if (ActualFixIt.getText () != Expected.Text )
364402 continue ;
365403
366- auto &ActualRange = ActualFixIt.getLineColumnRange (SM, BufferID );
404+ auto &ActualRange = ActualFixIt.getLineColumnRange (SM);
367405
368406 if (Expected.Range .StartCol != ActualRange.StartCol ||
369407 Expected.Range .EndCol != ActualRange.EndCol ||
@@ -394,7 +432,7 @@ DiagnosticVerifier::renderFixits(ArrayRef<CapturedFixItInfo> ActualFixIts,
394432 interleave (
395433 ActualFixIts,
396434 [&](const CapturedFixItInfo &ActualFixIt) {
397- auto &ActualRange = ActualFixIt.getLineColumnRange (SM, BufferID );
435+ auto &ActualRange = ActualFixIt.getLineColumnRange (SM);
398436 OS << " {{" ;
399437
400438 if (ActualRange.StartLine != DiagnosticLineNo)
@@ -566,7 +604,6 @@ DiagnosticVerifier::Result DiagnosticVerifier::verifyFile(unsigned BufferID) {
566604
567605 const SourceLoc BufferStartLoc = SM.getLocForBufferStart (BufferID);
568606 StringRef InputFile = SM.getEntireTextForBuffer (BufferID);
569- StringRef BufferName = SM.getIdentifierForBuffer (BufferID);
570607
571608 // Queue up all of the diagnostics, allowing us to sort them and emit them in
572609 // file order.
@@ -709,7 +746,7 @@ DiagnosticVerifier::Result DiagnosticVerifier::verifyFile(unsigned BufferID) {
709746 if (PrevExpectedContinuationLine)
710747 Expected.LineNo = PrevExpectedContinuationLine;
711748 else
712- Expected.LineNo = SM.getPresumedLineAndColumnForLoc (
749+ Expected.LineNo = SM.getLineAndColumnInBuffer (
713750 BufferStartLoc.getAdvancedLoc (MatchStart.data () -
714751 InputFile.data ()),
715752 BufferID)
@@ -888,7 +925,7 @@ DiagnosticVerifier::Result DiagnosticVerifier::verifyFile(unsigned BufferID) {
888925
889926 // Check to see if we had this expected diagnostic.
890927 auto FoundDiagnosticInfo =
891- findDiagnostic (CapturedDiagnostics, expected, BufferName );
928+ findDiagnostic (CapturedDiagnostics, expected, BufferID );
892929 auto FoundDiagnosticIter = std::get<0 >(FoundDiagnosticInfo);
893930 if (FoundDiagnosticIter == CapturedDiagnostics.end ()) {
894931 // Diagnostic didn't exist. If this is a 'mayAppear' diagnostic, then
@@ -1078,8 +1115,8 @@ DiagnosticVerifier::Result DiagnosticVerifier::verifyFile(unsigned BufferID) {
10781115 auto I = CapturedDiagnostics.begin ();
10791116 for (auto E = CapturedDiagnostics.end (); I != E; ++I) {
10801117 // 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 )
10831120 continue ;
10841121
10851122 // Otherwise, we found it, break out.
@@ -1167,7 +1204,7 @@ DiagnosticVerifier::Result DiagnosticVerifier::verifyFile(unsigned BufferID) {
11671204 bool HadUnexpectedDiag = false ;
11681205 auto CapturedDiagIter = CapturedDiagnostics.begin ();
11691206 while (CapturedDiagIter != CapturedDiagnostics.end ()) {
1170- if (CapturedDiagIter->FileName != BufferName ) {
1207+ if (CapturedDiagIter->SourceBufferID != BufferID ) {
11711208 ++CapturedDiagIter;
11721209 continue ;
11731210 }
@@ -1241,7 +1278,7 @@ void DiagnosticVerifier::handleDiagnostic(SourceManager &SM,
12411278 const DiagnosticInfo &Info) {
12421279 SmallVector<CapturedFixItInfo, 2 > fixIts;
12431280 for (const auto &fixIt : Info.FixIts ) {
1244- fixIts.emplace_back (fixIt);
1281+ fixIts.emplace_back (SM, fixIt);
12451282 }
12461283
12471284 llvm::SmallVector<std::string, 1 > eduNotes;
@@ -1256,40 +1293,39 @@ void DiagnosticVerifier::handleDiagnostic(SourceManager &SM,
12561293 Info.FormatArgs );
12571294 }
12581295
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);
12861300}
12871301
12881302// / Once all diagnostics have been captured, perform verification.
12891303bool DiagnosticVerifier::finishProcessing () {
12901304 DiagnosticVerifier::Result Result = {false , false };
12911305
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 };
12931329 for (ArrayRef<unsigned > BufferIDList : BufferIDLists)
12941330 for (auto &BufferID : BufferIDList) {
12951331 DiagnosticVerifier::Result FileResult = verifyFile (BufferID);
0 commit comments