|
72 | 72 | #include "llvm/Support/YAMLTraits.h"
|
73 | 73 | #include <algorithm>
|
74 | 74 | #include <memory>
|
| 75 | +#include <utility> |
75 | 76 |
|
76 | 77 | using namespace swift;
|
77 | 78 | using namespace importer;
|
@@ -2256,6 +2257,109 @@ ClangModuleUnit *ClangImporter::Implementation::getClangModuleForDecl(
|
2256 | 2257 | return getWrapperForModule(M);
|
2257 | 2258 | }
|
2258 | 2259 |
|
| 2260 | +// TODO: Consolidate with importSourceLoc below |
| 2261 | +SourceLoc ClangImporter::Implementation::convertSourceLocation( |
| 2262 | + const clang::SourceLocation &loc) { |
| 2263 | + return getBufferImporterForDiagnostics().resolveSourceLocation( |
| 2264 | + getClangASTContext().getSourceManager(), loc); |
| 2265 | +} |
| 2266 | + |
| 2267 | +SwiftLookupTable::SingleEntry |
| 2268 | +ClangImporter::Implementation::getDiagnosticTarget() { |
| 2269 | + return diagnosticTarget; |
| 2270 | +} |
| 2271 | + |
| 2272 | +template <typename T> |
| 2273 | +T ClangImporter::Implementation::withDiagnosticTargetIfNotAlreadyReported( |
| 2274 | + const SwiftLookupTable::SingleEntry &target, std::function<T()> fn) { |
| 2275 | + bool alreadyReported = reportedDiagnosticTargets.count(target); |
| 2276 | + if (!alreadyReported && !getEagerImportActive()) { |
| 2277 | + reportedDiagnosticTargets.insert(target); |
| 2278 | + return withDiagnosticTarget(target, fn); |
| 2279 | + } |
| 2280 | + |
| 2281 | + return fn(); |
| 2282 | +} |
| 2283 | + |
| 2284 | +template <typename T> |
| 2285 | +T ClangImporter::Implementation::withDiagnosticTarget( |
| 2286 | + const SwiftLookupTable::SingleEntry &target, std::function<T()> fn) { |
| 2287 | + assert(target); |
| 2288 | + // In some situations, the ClangImporter is invoked in a reentrant manner, |
| 2289 | + // resulting in a diagnosticTarget already being set. In such a case, we |
| 2290 | + // keep the outer diagnostic target. |
| 2291 | + llvm::SaveAndRestore<SwiftLookupTable::SingleEntry> sar{diagnosticTarget}; |
| 2292 | + if (!diagnosticTarget) { |
| 2293 | + diagnosticTarget = target; |
| 2294 | + } |
| 2295 | + return fn(); |
| 2296 | +} |
| 2297 | + |
| 2298 | +bool ClangImporter::Implementation::isDiagnosticTarget( |
| 2299 | + const SwiftLookupTable::SingleEntry &targetCandidate) const { |
| 2300 | + return diagnosticTarget == targetCandidate; |
| 2301 | +} |
| 2302 | +bool ClangImporter::Implementation::isDiagnosticTarget( |
| 2303 | + const clang::NamedDecl *targetCandidate) const { |
| 2304 | + return diagnosticTarget.dyn_cast<clang::NamedDecl *>() == targetCandidate; |
| 2305 | +} |
| 2306 | +bool ClangImporter::Implementation::isDiagnosticTarget( |
| 2307 | + const clang::ModuleMacro *targetCandidate) const { |
| 2308 | + return diagnosticTarget.dyn_cast<clang::ModuleMacro *>() == targetCandidate; |
| 2309 | +} |
| 2310 | +bool ClangImporter::Implementation::isDiagnosticTarget( |
| 2311 | + const clang::MacroInfo *targetCandidate) const { |
| 2312 | + return diagnosticTarget.dyn_cast<clang::MacroInfo *>() == targetCandidate; |
| 2313 | +} |
| 2314 | + |
| 2315 | +bool ClangImporter::Implementation::getEagerImportActive() { |
| 2316 | + return eagerImportActive; |
| 2317 | +} |
| 2318 | + |
| 2319 | +void ClangImporter::Implementation::ifTargetMatchesReportErrorAndConsumeNotes( |
| 2320 | + const clang::NamedDecl *target, Diagnostic &&error, |
| 2321 | + const clang::SourceLocation &loc) { |
| 2322 | + if (!(SwiftContext.LangOpts.EnableExperimentalClangImporterDiagnostics && |
| 2323 | + isDiagnosticTarget(target))) |
| 2324 | + return; |
| 2325 | + |
| 2326 | + const SourceLoc convertedLoc = convertSourceLocation(loc); |
| 2327 | + diagnose(convertedLoc, error); |
| 2328 | + while (!pendingErrorNotes.empty()) { |
| 2329 | + auto pendingErrorNote = pendingErrorNotes.back(); |
| 2330 | + if (!pendingErrorNote.diag.getLoc()) { |
| 2331 | + pendingErrorNote.diag.setLoc(convertedLoc); |
| 2332 | + } |
| 2333 | + if (isDiagnosticTarget(pendingErrorNote.target)) { |
| 2334 | + diagnose(pendingErrorNote.diag.getLoc(), pendingErrorNote.diag); |
| 2335 | + } |
| 2336 | + pendingErrorNotes.pop_back(); |
| 2337 | + } |
| 2338 | +} |
| 2339 | + |
| 2340 | +void ClangImporter::Implementation::addPendingErrorNote(Diagnostic &¬e) { |
| 2341 | + addPendingErrorNote(std::move(note), clang::SourceLocation()); |
| 2342 | +} |
| 2343 | + |
| 2344 | +void ClangImporter::Implementation::addPendingErrorNote( |
| 2345 | + Diagnostic &¬e, const clang::SourceLocation &loc) { |
| 2346 | + if (!(SwiftContext.LangOpts.EnableExperimentalClangImporterDiagnostics && |
| 2347 | + getDiagnosticTarget())) |
| 2348 | + return; |
| 2349 | + note.setLoc(convertSourceLocation(loc)); |
| 2350 | + pendingErrorNotes.push_back({note, getDiagnosticTarget()}); |
| 2351 | +} |
| 2352 | + |
| 2353 | +void ClangImporter::Implementation::applySourceLocationToNotesWithoutLocation( |
| 2354 | + const clang::SourceLocation &loc) { |
| 2355 | + const SourceLoc convertedLoc = convertSourceLocation(loc); |
| 2356 | + for (auto &pendingErrorNote : pendingErrorNotes) { |
| 2357 | + if (!pendingErrorNote.diag.getLoc()) { |
| 2358 | + pendingErrorNote.diag.setLoc(convertedLoc); |
| 2359 | + } |
| 2360 | + } |
| 2361 | +} |
| 2362 | + |
2259 | 2363 | #pragma mark Source locations
|
2260 | 2364 | clang::SourceLocation
|
2261 | 2365 | ClangImporter::Implementation::exportSourceLoc(SourceLoc loc) {
|
@@ -3860,21 +3964,31 @@ void ClangImporter::Implementation::lookupValue(
|
3860 | 3964 | // If it's a Clang declaration, try to import it.
|
3861 | 3965 | if (auto clangDecl = entry.dyn_cast<clang::NamedDecl *>()) {
|
3862 | 3966 | bool isNamespace = isa<clang::NamespaceDecl>(clangDecl);
|
3863 |
| - Decl *realDecl = |
3864 |
| - importDeclReal(clangDecl->getMostRecentDecl(), CurrentVersion, |
3865 |
| - /*useCanonicalDecl*/ !isNamespace); |
| 3967 | + Decl *realDecl = withDiagnosticTargetIfNotAlreadyReported( |
| 3968 | + clangDecl->getMostRecentDecl(), |
| 3969 | + std::function<Decl *()>([&]() -> Decl * { |
| 3970 | + return importDeclReal(clangDecl->getMostRecentDecl(), |
| 3971 | + CurrentVersion, |
| 3972 | + /*useCanonicalDecl*/ !isNamespace); |
| 3973 | + })); |
3866 | 3974 |
|
3867 | 3975 | if (!realDecl)
|
3868 | 3976 | continue;
|
3869 | 3977 | decl = cast<ValueDecl>(realDecl);
|
3870 | 3978 | if (!decl) continue;
|
3871 | 3979 | } else if (!name.isSpecial()) {
|
3872 | 3980 | // Try to import a macro.
|
3873 |
| - if (auto modMacro = entry.dyn_cast<clang::ModuleMacro *>()) |
3874 |
| - decl = importMacro(name.getBaseIdentifier(), modMacro); |
3875 |
| - else if (auto clangMacro = entry.dyn_cast<clang::MacroInfo *>()) |
3876 |
| - decl = importMacro(name.getBaseIdentifier(), clangMacro); |
3877 |
| - else |
| 3981 | + if (auto modMacro = entry.dyn_cast<clang::ModuleMacro *>()) { |
| 3982 | + decl = withDiagnosticTargetIfNotAlreadyReported( |
| 3983 | + modMacro, std::function<ValueDecl *()>([&]() { |
| 3984 | + return importMacro(name.getBaseIdentifier(), modMacro); |
| 3985 | + })); |
| 3986 | + } else if (auto clangMacro = entry.dyn_cast<clang::MacroInfo *>()) { |
| 3987 | + decl = withDiagnosticTargetIfNotAlreadyReported( |
| 3988 | + clangMacro, std::function<ValueDecl *()>([&]() { |
| 3989 | + return importMacro(name.getBaseIdentifier(), clangMacro); |
| 3990 | + })); |
| 3991 | + } else |
3878 | 3992 | llvm_unreachable("new kind of lookup table entry");
|
3879 | 3993 | if (!decl) continue;
|
3880 | 3994 | } else {
|
@@ -3954,6 +4068,9 @@ void ClangImporter::Implementation::lookupValue(
|
3954 | 4068 | void ClangImporter::Implementation::lookupVisibleDecls(
|
3955 | 4069 | SwiftLookupTable &table,
|
3956 | 4070 | VisibleDeclConsumer &consumer) {
|
| 4071 | + |
| 4072 | + llvm::SaveAndRestore<bool> sar(eagerImportActive, true); |
| 4073 | + |
3957 | 4074 | // Retrieve and sort all of the base names in this particular table.
|
3958 | 4075 | auto baseNames = table.allBaseNames();
|
3959 | 4076 | llvm::array_pod_sort(baseNames.begin(), baseNames.end());
|
@@ -4128,6 +4245,28 @@ TinyPtrVector<ValueDecl *> ClangRecordMemberLookup::evaluate(
|
4128 | 4245 | return result;
|
4129 | 4246 | }
|
4130 | 4247 |
|
| 4248 | +bool ClangImporter::Implementation::diagnosticsProducedForNamedMembers( |
| 4249 | + const IterableDeclContext *IDC, DeclBaseName N, uint64_t contextData) { |
| 4250 | + auto *D = IDC->getDecl(); |
| 4251 | + auto *DC = D->getInnermostDeclContext(); |
| 4252 | + auto *CD = D->getClangDecl(); |
| 4253 | + auto CMO = getClangSubmoduleForDecl(CD); |
| 4254 | + auto *nominal = DC->getSelfNominalTypeDecl(); |
| 4255 | + auto effectiveClangContext = getEffectiveClangContext(nominal); |
| 4256 | + auto table = findLookupTable(*CMO); |
| 4257 | + |
| 4258 | + for (auto entry : |
| 4259 | + table->lookup(SerializedSwiftName(N), effectiveClangContext)) { |
| 4260 | + if (auto member = entry.dyn_cast<clang::NamedDecl *>()) { |
| 4261 | + if (!reportedDiagnosticTargets.count(member)) { |
| 4262 | + return false; |
| 4263 | + } |
| 4264 | + } |
| 4265 | + } |
| 4266 | + |
| 4267 | + return true; |
| 4268 | +} |
| 4269 | + |
4131 | 4270 | TinyPtrVector<ValueDecl *>
|
4132 | 4271 | ClangImporter::Implementation::loadNamedMembers(
|
4133 | 4272 | const IterableDeclContext *IDC, DeclBaseName N, uint64_t contextData) {
|
@@ -4189,7 +4328,10 @@ ClangImporter::Implementation::loadNamedMembers(
|
4189 | 4328 | if (member->getDeclContext() != CDC) continue;
|
4190 | 4329 |
|
4191 | 4330 | SmallVector<Decl*, 4> tmp;
|
4192 |
| - insertMembersAndAlternates(member, tmp); |
| 4331 | + withDiagnosticTargetIfNotAlreadyReported( |
| 4332 | + member, std::function<void()>( |
| 4333 | + [&]() { insertMembersAndAlternates(member, tmp); })); |
| 4334 | + |
4193 | 4335 | for (auto *TD : tmp) {
|
4194 | 4336 | if (auto *V = dyn_cast<ValueDecl>(TD)) {
|
4195 | 4337 | // Skip ValueDecls if they import under different names.
|
@@ -4479,5 +4621,8 @@ ClangImporter::getEffectiveClangContext(const NominalTypeDecl *nominal) {
|
4479 | 4621 | }
|
4480 | 4622 |
|
4481 | 4623 | Decl *ClangImporter::importDeclDirectly(const clang::NamedDecl *decl) {
|
4482 |
| - return Impl.importDecl(decl, Impl.CurrentVersion); |
| 4624 | + return Impl.withDiagnosticTargetIfNotAlreadyReported( |
| 4625 | + const_cast<clang::NamedDecl *>(decl), std::function<Decl *()>([&]() { |
| 4626 | + return Impl.importDecl(decl, Impl.CurrentVersion); |
| 4627 | + })); |
4483 | 4628 | }
|
0 commit comments