|
40 | 40 | #include "swift/ClangImporter/SwiftAbstractBasicReader.h"
|
41 | 41 | #include "swift/Serialization/SerializedModuleLoader.h"
|
42 | 42 | #include "clang/AST/DeclTemplate.h"
|
| 43 | +#include "clang/Basic/SourceManager.h" |
43 | 44 | #include "llvm/ADT/Statistic.h"
|
44 | 45 | #include "llvm/Support/Compiler.h"
|
45 | 46 | #include "llvm/Support/Debug.h"
|
@@ -185,7 +186,7 @@ SourceLoc ModuleFile::getSourceLoc() const {
|
185 | 186 | auto filename = getModuleFilename();
|
186 | 187 | auto bufferID = SourceMgr.getIDForBufferIdentifier(filename);
|
187 | 188 | if (!bufferID)
|
188 |
| - bufferID = SourceMgr.addMemBufferCopy(StringRef(), filename); |
| 189 | + bufferID = SourceMgr.addMemBufferCopy("<binary format>", filename); |
189 | 190 | return SourceMgr.getLocForBufferStart(*bufferID);
|
190 | 191 | }
|
191 | 192 |
|
@@ -238,6 +239,103 @@ ModularizationError::diagnose(const ModuleFile *MF,
|
238 | 239 | // We could pass along the `path` information through notes.
|
239 | 240 | // However, for a top-level decl a path would just duplicate the
|
240 | 241 | // 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 | + } |
241 | 339 | }
|
242 | 340 |
|
243 | 341 | void TypeError::diagnose(const ModuleFile *MF) const {
|
@@ -2064,7 +2162,7 @@ ModuleFile::resolveCrossReference(ModuleID MID, uint32_t pathLen) {
|
2064 | 2162 | [&](const ModularizationError &modularError) {
|
2065 | 2163 | modularError.diagnose(this, DiagnosticBehavior::Warning);
|
2066 | 2164 | });
|
2067 |
| - getContext().Diags.diagnose(getSourceLoc(), |
| 2165 | + getContext().Diags.diagnose(SourceLoc(), |
2068 | 2166 | diag::modularization_issue_worked_around);
|
2069 | 2167 | } else {
|
2070 | 2168 | return std::move(error);
|
|
0 commit comments