|
18 | 18 | #include "TypeChecker.h"
|
19 | 19 | #include "clang/AST/DeclObjC.h"
|
20 | 20 | #include "swift/AST/ASTContext.h"
|
| 21 | +#include "swift/AST/ClangModuleLoader.h" |
21 | 22 | #include "swift/AST/GenericSignature.h"
|
22 | 23 | #include "swift/AST/ImportCache.h"
|
23 | 24 | #include "swift/AST/Initializer.h"
|
|
29 | 30 | #include "swift/AST/SourceFile.h"
|
30 | 31 | #include "swift/Basic/SourceManager.h"
|
31 | 32 | #include "swift/Basic/STLExtras.h"
|
| 33 | +#include "swift/ClangImporter/ClangImporterRequests.h" |
32 | 34 | #include "swift/Sema/IDETypeCheckingRequests.h"
|
33 | 35 | #include "swift/Sema/IDETypeChecking.h"
|
| 36 | +#include "clang/Basic/Module.h" |
| 37 | +#include "clang/Lex/Preprocessor.h" |
34 | 38 | #include "llvm/ADT/SetVector.h"
|
35 | 39 | #include <set>
|
36 | 40 |
|
@@ -558,6 +562,63 @@ static void
|
558 | 562 | getReasonForSuper(Reason), Sig, Visited);
|
559 | 563 | }
|
560 | 564 |
|
| 565 | +static void lookupVisibleCxxNamespaceMemberDecls( |
| 566 | + EnumDecl *swiftDecl, const clang::NamespaceDecl *clangNamespace, |
| 567 | + VisibleDeclConsumer &Consumer, VisitedSet &Visited) { |
| 568 | + if (!Visited.insert(swiftDecl).second) |
| 569 | + return; |
| 570 | + auto &ctx = swiftDecl->getASTContext(); |
| 571 | + auto namespaceDecl = clangNamespace; |
| 572 | + |
| 573 | + // This is only to keep track of the members we've already seen. |
| 574 | + llvm::SmallPtrSet<Decl *, 16> addedMembers; |
| 575 | + for (auto redecl : namespaceDecl->redecls()) { |
| 576 | + for (auto member : redecl->decls()) { |
| 577 | + auto lookupAndAddMembers = [&](DeclName name) { |
| 578 | + auto allResults = evaluateOrDefault( |
| 579 | + ctx.evaluator, ClangDirectLookupRequest({swiftDecl, redecl, name}), |
| 580 | + {}); |
| 581 | + |
| 582 | + for (auto found : allResults) { |
| 583 | + auto clangMember = found.get<clang::NamedDecl *>(); |
| 584 | + if (auto importedDecl = |
| 585 | + ctx.getClangModuleLoader()->importDeclDirectly( |
| 586 | + cast<clang::NamedDecl>(clangMember))) { |
| 587 | + if (addedMembers.insert(importedDecl).second) { |
| 588 | + if (importedDecl->getDeclContext()->getAsDecl() != swiftDecl) { |
| 589 | + return; |
| 590 | + } |
| 591 | + Consumer.foundDecl(cast<ValueDecl>(importedDecl), |
| 592 | + DeclVisibilityKind::MemberOfCurrentNominal); |
| 593 | + } |
| 594 | + } |
| 595 | + } |
| 596 | + }; |
| 597 | + |
| 598 | + auto namedDecl = dyn_cast<clang::NamedDecl>(member); |
| 599 | + if (!namedDecl) |
| 600 | + continue; |
| 601 | + auto name = ctx.getClangModuleLoader()->importName(namedDecl); |
| 602 | + if (!name) |
| 603 | + continue; |
| 604 | + lookupAndAddMembers(name); |
| 605 | + |
| 606 | + // Unscoped enums could have their enumerators present |
| 607 | + // in the parent namespace. |
| 608 | + if (auto *ed = dyn_cast<clang::EnumDecl>(member)) { |
| 609 | + if (!ed->isScoped()) { |
| 610 | + for (const auto *ecd : ed->enumerators()) { |
| 611 | + auto name = ctx.getClangModuleLoader()->importName(ecd); |
| 612 | + if (!name) |
| 613 | + continue; |
| 614 | + lookupAndAddMembers(name); |
| 615 | + } |
| 616 | + } |
| 617 | + } |
| 618 | + } |
| 619 | + } |
| 620 | +} |
| 621 | + |
561 | 622 | static void lookupVisibleMemberDeclsImpl(
|
562 | 623 | Type BaseTy, VisibleDeclConsumer &Consumer, const DeclContext *CurrDC,
|
563 | 624 | LookupState LS, DeclVisibilityKind Reason, GenericSignature Sig,
|
@@ -647,6 +708,16 @@ static void lookupVisibleMemberDeclsImpl(
|
647 | 708 | return;
|
648 | 709 | }
|
649 | 710 |
|
| 711 | + // Lookup members of C++ namespace without looking type members, as |
| 712 | + // C++ namespace uses lazy lookup. |
| 713 | + if (auto *ET = BaseTy->getAs<EnumType>()) { |
| 714 | + if (auto *clangNamespace = dyn_cast_or_null<clang::NamespaceDecl>( |
| 715 | + ET->getDecl()->getClangDecl())) { |
| 716 | + lookupVisibleCxxNamespaceMemberDecls(ET->getDecl(), clangNamespace, |
| 717 | + Consumer, Visited); |
| 718 | + } |
| 719 | + } |
| 720 | + |
650 | 721 | // If we're looking into a type parameter and we have a GenericSignature,
|
651 | 722 | // query the signature to resolve where we should look.
|
652 | 723 | if (BaseTy->isTypeParameter() && Sig) {
|
|
0 commit comments