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,10 +186,25 @@ 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
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
+
192
208
void
193
209
ModularizationError::diagnose (const ModuleFile *MF,
194
210
DiagnosticBehavior limit) const {
@@ -197,18 +213,21 @@ ModularizationError::diagnose(const ModuleFile *MF,
197
213
auto diagnoseError = [&](Kind errorKind) {
198
214
switch (errorKind) {
199
215
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);
203
220
case Kind::DeclKindChanged:
204
221
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);
209
227
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);
212
231
}
213
232
llvm_unreachable (" Unhandled ModularizationError::Kind in switch." );
214
233
};
@@ -220,6 +239,103 @@ ModularizationError::diagnose(const ModuleFile *MF,
220
239
// We could pass along the `path` information through notes.
221
240
// However, for a top-level decl a path would just duplicate the
222
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
+ }
223
339
}
224
340
225
341
void TypeError::diagnose (const ModuleFile *MF) const {
@@ -1957,7 +2073,7 @@ ModuleFile::resolveCrossReference(ModuleID MID, uint32_t pathLen) {
1957
2073
SmallVector<char , 64 > strScratch;
1958
2074
1959
2075
auto errorKind = ModularizationError::Kind::DeclNotFound;
1960
- Identifier foundIn;
2076
+ ModuleDecl * foundIn = nullptr ;
1961
2077
bool isType = false ;
1962
2078
1963
2079
if (recordID == XREF_TYPE_PATH_PIECE ||
@@ -2011,28 +2127,26 @@ ModuleFile::resolveCrossReference(ModuleID MID, uint32_t pathLen) {
2011
2127
// one because otherwise it would have succeeded on the first search.
2012
2128
// This is usually caused by the use of poorly modularized headers.
2013
2129
errorKind = ModularizationError::Kind::DeclMoved;
2014
- foundIn = otherModule-> getName () ;
2130
+ foundIn = otherModule;
2015
2131
break ;
2016
2132
} else if (hadAMatchBeforeFiltering) {
2017
2133
// Found a match that was filtered out. This may be from the same
2018
2134
// expected module if there's a type difference. This can be caused
2019
2135
// by the use of different Swift language versions between a library
2020
2136
// with serialized SIL and a client.
2021
2137
errorKind = ModularizationError::Kind::DeclKindChanged;
2022
- foundIn = otherModule-> getName () ;
2138
+ foundIn = otherModule;
2023
2139
break ;
2024
2140
}
2025
2141
}
2026
2142
}
2027
2143
2028
2144
auto declName = getXRefDeclNameForError ();
2029
- auto expectedIn = baseModule->getName ();
2030
- auto referencedFrom = getName ();
2031
2145
auto error = llvm::make_error<ModularizationError>(declName,
2032
2146
isType,
2033
2147
errorKind,
2034
- expectedIn ,
2035
- referencedFrom ,
2148
+ baseModule ,
2149
+ this ,
2036
2150
foundIn,
2037
2151
pathTrace);
2038
2152
@@ -2043,13 +2157,13 @@ ModuleFile::resolveCrossReference(ModuleID MID, uint32_t pathLen) {
2043
2157
if (getContext ().LangOpts .ForceWorkaroundBrokenModules &&
2044
2158
errorKind == ModularizationError::Kind::DeclMoved &&
2045
2159
!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.
2049
2161
llvm::handleAllErrors (std::move (error),
2050
2162
[&](const ModularizationError &modularError) {
2051
- modularError.diagnose (this , DiagnosticBehavior::Note );
2163
+ modularError.diagnose (this , DiagnosticBehavior::Warning );
2052
2164
});
2165
+ getContext ().Diags .diagnose (SourceLoc (),
2166
+ diag::modularization_issue_worked_around);
2053
2167
} else {
2054
2168
return std::move (error);
2055
2169
}
0 commit comments