4040#include " swift/ClangImporter/SwiftAbstractBasicReader.h"
4141#include " swift/Serialization/SerializedModuleLoader.h"
4242#include " clang/AST/DeclTemplate.h"
43+ #include " clang/Basic/SourceManager.h"
4344#include " llvm/ADT/Statistic.h"
4445#include " llvm/Support/Compiler.h"
4546#include " llvm/Support/Debug.h"
@@ -185,10 +186,25 @@ SourceLoc ModuleFile::getSourceLoc() const {
185186 auto filename = getModuleFilename ();
186187 auto bufferID = SourceMgr.getIDForBufferIdentifier (filename);
187188 if (!bufferID)
188- bufferID = SourceMgr.addMemBufferCopy (StringRef () , filename);
189+ bufferID = SourceMgr.addMemBufferCopy (" <binary format> " , filename);
189190 return SourceMgr.getLocForBufferStart (*bufferID);
190191}
191192
193+ SourceLoc ModularizationError::getSourceLoc () const {
194+ auto &SourceMgr = referenceModule->getContext ().Diags .SourceMgr ;
195+ auto filename = referenceModule->getModuleFilename ();
196+
197+ // Synthesize some context. We don't have an actual decl here
198+ // so try to print a simple representation of the reference.
199+ std::string S;
200+ llvm::raw_string_ostream OS (S);
201+ OS << expectedModule->getName () << " ." << name;
202+
203+ // If we enable these remarks by default we may want to reuse these buffers.
204+ auto bufferID = SourceMgr.addMemBufferCopy (S, filename);
205+ return SourceMgr.getLocForBufferStart (bufferID);
206+ }
207+
192208void
193209ModularizationError::diagnose (const ModuleFile *MF,
194210 DiagnosticBehavior limit) const {
@@ -197,18 +213,21 @@ ModularizationError::diagnose(const ModuleFile *MF,
197213 auto diagnoseError = [&](Kind errorKind) {
198214 switch (errorKind) {
199215 case Kind::DeclMoved:
200- return ctx.Diags .diagnose (MF->getSourceLoc (), diag::modularization_issue_decl_moved,
201- declIsType, name, expectedModuleName,
202- foundModuleName);
216+ return ctx.Diags .diagnose (getSourceLoc (),
217+ diag::modularization_issue_decl_moved,
218+ declIsType, name, expectedModule,
219+ foundModule);
203220 case Kind::DeclKindChanged:
204221 return
205- ctx.Diags .diagnose (MF->getSourceLoc (), diag::modularization_issue_decl_type_changed,
206- declIsType, name, expectedModuleName,
207- referencedFromModuleName, foundModuleName,
208- foundModuleName != expectedModuleName);
222+ ctx.Diags .diagnose (getSourceLoc (),
223+ diag::modularization_issue_decl_type_changed,
224+ declIsType, name, expectedModule,
225+ referenceModule->getName (), foundModule,
226+ foundModule != expectedModule);
209227 case Kind::DeclNotFound:
210- return ctx.Diags .diagnose (MF->getSourceLoc (), diag::modularization_issue_decl_not_found,
211- declIsType, name, expectedModuleName);
228+ return ctx.Diags .diagnose (getSourceLoc (),
229+ diag::modularization_issue_decl_not_found,
230+ declIsType, name, expectedModule);
212231 }
213232 llvm_unreachable (" Unhandled ModularizationError::Kind in switch." );
214233 };
@@ -220,6 +239,103 @@ ModularizationError::diagnose(const ModuleFile *MF,
220239 // We could pass along the `path` information through notes.
221240 // However, for a top-level decl a path would just duplicate the
222241 // expected module name and the decl name from the diagnostic.
242+
243+ // Show context with relevant file paths.
244+ ctx.Diags .diagnose (SourceLoc (),
245+ diag::modularization_issue_note_expected,
246+ declIsType, expectedModule,
247+ expectedModule->getModuleSourceFilename ());
248+
249+ const clang::Module *expectedUnderlying =
250+ expectedModule->findUnderlyingClangModule ();
251+ if (!expectedModule->isNonSwiftModule () &&
252+ expectedUnderlying) {
253+ auto CML = ctx.getClangModuleLoader ();
254+ auto &CSM = CML->getClangASTContext ().getSourceManager ();
255+ StringRef filename = CSM.getFilename (expectedUnderlying->DefinitionLoc );
256+ ctx.Diags .diagnose (SourceLoc (),
257+ diag::modularization_issue_note_expected_underlying,
258+ expectedUnderlying->Name ,
259+ filename);
260+ }
261+
262+ if (foundModule)
263+ ctx.Diags .diagnose (SourceLoc (),
264+ diag::modularization_issue_note_found,
265+ declIsType, foundModule,
266+ foundModule->getModuleSourceFilename ());
267+
268+ // A Swift language version mismatch could lead to a different set of rules
269+ // from APINotes files being applied when building the module vs when reading
270+ // from it.
271+ version::Version
272+ moduleLangVersion = referenceModule->getCompatibilityVersion (),
273+ clientLangVersion = MF->getContext ().LangOpts .EffectiveLanguageVersion ;
274+ ModuleDecl *referenceModuleDecl = referenceModule->getAssociatedModule ();
275+ if (clientLangVersion != moduleLangVersion) {
276+ ctx.Diags .diagnose (SourceLoc (),
277+ diag::modularization_issue_swift_version,
278+ referenceModuleDecl, moduleLangVersion,
279+ clientLangVersion);
280+ }
281+
282+ // If the error is in a resilient swiftmodule adjacent to a swiftinterface,
283+ // deleting the module to rebuild from the swiftinterface may fix the issue.
284+ // Limit this suggestion to distributed Swift modules to not hint at
285+ // deleting local caches and such.
286+ bool referenceModuleIsDistributed = referenceModuleDecl &&
287+ referenceModuleDecl->isNonUserModule ();
288+ if (referenceModule->getResilienceStrategy () ==
289+ ResilienceStrategy::Resilient &&
290+ referenceModuleIsDistributed) {
291+ ctx.Diags .diagnose (SourceLoc (),
292+ diag::modularization_issue_stale_module,
293+ referenceModuleDecl,
294+ referenceModule->getModuleFilename ());
295+ }
296+
297+ // If the missing decl was expected to be in a clang module,
298+ // it may be hidden by some clang defined passed via `-Xcc` affecting how
299+ // headers are seen.
300+ if (expectedUnderlying) {
301+ ctx.Diags .diagnose (SourceLoc (),
302+ diag::modularization_issue_audit_headers,
303+ expectedModule->isNonSwiftModule (), expectedModule);
304+ }
305+
306+ // If the reference goes from a distributed module to a local module,
307+ // the compiler may have picked up an undesired module. We usually expect
308+ // distributed modules to only reference other distributed modules.
309+ // Local modules can reference both local modules and distributed modules.
310+ if (referenceModuleIsDistributed) {
311+ if (!expectedModule->isNonUserModule ()) {
312+ ctx.Diags .diagnose (SourceLoc (),
313+ diag::modularization_issue_layering_expected_local,
314+ referenceModuleDecl, expectedModule);
315+ } else if (foundModule && !foundModule->isNonUserModule ()) {
316+ ctx.Diags .diagnose (SourceLoc (),
317+ diag::modularization_issue_layering_found_local,
318+ referenceModuleDecl, foundModule);
319+ }
320+ }
321+
322+ // If a type moved between MyModule and MyModule_Private, it can be caused
323+ // by the use of `-Xcc -D` to change the API of the modules, leading to
324+ // decls moving between both modules.
325+ if (errorKind == Kind::DeclMoved ||
326+ errorKind == Kind::DeclKindChanged) {
327+ StringRef foundModuleName = foundModule->getName ().str ();
328+ StringRef expectedModuleName = expectedModule->getName ().str ();
329+ if (foundModuleName != expectedModuleName &&
330+ (foundModuleName.startswith (expectedModuleName) ||
331+ expectedModuleName.startswith (foundModuleName)) &&
332+ (expectedUnderlying ||
333+ expectedModule->findUnderlyingClangModule ())) {
334+ ctx.Diags .diagnose (SourceLoc (),
335+ diag::modularization_issue_related_modules,
336+ declIsType, name);
337+ }
338+ }
223339}
224340
225341void TypeError::diagnose (const ModuleFile *MF) const {
@@ -1957,7 +2073,7 @@ ModuleFile::resolveCrossReference(ModuleID MID, uint32_t pathLen) {
19572073 SmallVector<char , 64 > strScratch;
19582074
19592075 auto errorKind = ModularizationError::Kind::DeclNotFound;
1960- Identifier foundIn;
2076+ ModuleDecl * foundIn = nullptr ;
19612077 bool isType = false ;
19622078
19632079 if (recordID == XREF_TYPE_PATH_PIECE ||
@@ -2011,28 +2127,26 @@ ModuleFile::resolveCrossReference(ModuleID MID, uint32_t pathLen) {
20112127 // one because otherwise it would have succeeded on the first search.
20122128 // This is usually caused by the use of poorly modularized headers.
20132129 errorKind = ModularizationError::Kind::DeclMoved;
2014- foundIn = otherModule-> getName () ;
2130+ foundIn = otherModule;
20152131 break ;
20162132 } else if (hadAMatchBeforeFiltering) {
20172133 // Found a match that was filtered out. This may be from the same
20182134 // expected module if there's a type difference. This can be caused
20192135 // by the use of different Swift language versions between a library
20202136 // with serialized SIL and a client.
20212137 errorKind = ModularizationError::Kind::DeclKindChanged;
2022- foundIn = otherModule-> getName () ;
2138+ foundIn = otherModule;
20232139 break ;
20242140 }
20252141 }
20262142 }
20272143
20282144 auto declName = getXRefDeclNameForError ();
2029- auto expectedIn = baseModule->getName ();
2030- auto referencedFrom = getName ();
20312145 auto error = llvm::make_error<ModularizationError>(declName,
20322146 isType,
20332147 errorKind,
2034- expectedIn ,
2035- referencedFrom ,
2148+ baseModule ,
2149+ this ,
20362150 foundIn,
20372151 pathTrace);
20382152
@@ -2043,13 +2157,13 @@ ModuleFile::resolveCrossReference(ModuleID MID, uint32_t pathLen) {
20432157 if (getContext ().LangOpts .ForceWorkaroundBrokenModules &&
20442158 errorKind == ModularizationError::Kind::DeclMoved &&
20452159 !values.empty ()) {
2046- // Print the error as a remark and notify of the recovery attempt.
2047- getContext ().Diags .diagnose (getSourceLoc (),
2048- diag::modularization_issue_worked_around);
2160+ // Print the error as a warning and notify of the recovery attempt.
20492161 llvm::handleAllErrors (std::move (error),
20502162 [&](const ModularizationError &modularError) {
2051- modularError.diagnose (this , DiagnosticBehavior::Note );
2163+ modularError.diagnose (this , DiagnosticBehavior::Warning );
20522164 });
2165+ getContext ().Diags .diagnose (SourceLoc (),
2166+ diag::modularization_issue_worked_around);
20532167 } else {
20542168 return std::move (error);
20552169 }
0 commit comments