Skip to content

Commit 5bd6840

Browse files
committed
Index synthesized wrapper refs by substituting the Clang decl.
The goal of this change is replace the references to synthesized declarations, whose definitions are never contained in the indexstore, with references to the underlying declarations which are contained in the indexstore. The current behavior prevents code navigation from the references to the declaration. Reference: #79912 - I added the EnumElementDecl generated from the underlying Clang EnumConstantDecl to the imported decl cache for ClangImporter. - I took the effective Clang node and corresponding imported decl to substitute for "synthesized wrapper decls". This has a weird outcome, where a reference to the `Code` enum inside of the synthesized struct can emit 2 references to the underlying enum. There's an example in the test case, where `TestError.Code` is referenced. Fixes 79912 adding emitDataForSwiftSerializedModule emits the decls but: - The locations are all 0:0 - The decls are emitted in the file "module.modulemap
1 parent 5a92bc5 commit 5bd6840

File tree

3 files changed

+91
-1
lines changed

3 files changed

+91
-1
lines changed

lib/ClangImporter/ImportDecl.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2000,6 +2000,8 @@ namespace {
20002000
nominal->addMember(decl);
20012001
};
20022002

2003+
Impl.ImportedDecls[{constant->getCanonicalDecl(), getVersion()}] =
2004+
enumeratorDecl;
20032005
addDecl(result, enumeratorDecl);
20042006
for (auto *variant : variantDecls)
20052007
addDecl(result, variant);

lib/Index/Index.cpp

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,12 @@
3030
#include "swift/Basic/Assertions.h"
3131
#include "swift/Basic/SourceManager.h"
3232
#include "swift/Basic/StringExtras.h"
33+
#include "swift/ClangImporter/ClangImporter.h"
3334
#include "swift/IDE/SourceEntityWalker.h"
3435
#include "swift/IDE/Utils.h"
3536
#include "swift/Markup/Markup.h"
3637
#include "swift/Sema/IDETypeChecking.h"
38+
#include "clang/AST/Decl.h"
3739
#include "llvm/ADT/APInt.h"
3840
#include "llvm/ADT/SmallVector.h"
3941
#include "llvm/Support/ErrorHandling.h"
@@ -431,6 +433,7 @@ struct MappedLoc {
431433

432434
class IndexSwiftASTWalker : public SourceEntityWalker {
433435
IndexDataConsumer &IdxConsumer;
436+
ASTContext &Ctx;
434437
SourceManager &SrcMgr;
435438
std::optional<unsigned> BufferID;
436439
bool enableWarnings;
@@ -468,6 +471,31 @@ class IndexSwiftASTWalker : public SourceEntityWalker {
468471
// let bindings.
469472
llvm::DenseMap<ValueDecl *, ValueDecl *> sameNamedCaptures;
470473

474+
bool isImporterSynthesizedWrapper(ValueDecl *D) {
475+
const ClangImporterSynthesizedTypeAttr *attr =
476+
D->getAttrs().getAttribute<ClangImporterSynthesizedTypeAttr>();
477+
if (!attr) {
478+
const VarDecl *var = dyn_cast_or_null<VarDecl>(D);
479+
if (!var) {
480+
return false;
481+
}
482+
const NominalTypeDecl *type =
483+
var->getDeclContext()->getSelfNominalTypeDecl();
484+
if (!type ||
485+
!type->getAttrs().hasAttribute<ClangImporterSynthesizedTypeAttr>()) {
486+
return false;
487+
}
488+
attr = type->getAttrs().getAttribute<ClangImporterSynthesizedTypeAttr>();
489+
}
490+
switch (attr->getKind()) {
491+
case ClangImporterSynthesizedTypeAttr::Kind::NSErrorWrapper:
492+
case ClangImporterSynthesizedTypeAttr::Kind::NSErrorWrapperAnon:
493+
return true;
494+
default:
495+
return false;
496+
}
497+
}
498+
471499
bool getNameAndUSR(ValueDecl *D, ExtensionDecl *ExtD,
472500
StringRef &name, StringRef &USR) {
473501
auto &result = nameAndUSRCache[ExtD ? (Decl*)ExtD : D];
@@ -594,7 +622,7 @@ class IndexSwiftASTWalker : public SourceEntityWalker {
594622
public:
595623
IndexSwiftASTWalker(IndexDataConsumer &IdxConsumer, ASTContext &Ctx,
596624
SourceFile *SF = nullptr)
597-
: IdxConsumer(IdxConsumer), SrcMgr(Ctx.SourceMgr),
625+
: IdxConsumer(IdxConsumer), Ctx(Ctx), SrcMgr(Ctx.SourceMgr),
598626
BufferID(SF ? std::optional(SF->getBufferID()) : std::nullopt),
599627
enableWarnings(IdxConsumer.enableWarnings()) {}
600628

@@ -901,6 +929,23 @@ class IndexSwiftASTWalker : public SourceEntityWalker {
901929
return false;
902930
}
903931

932+
if (isImporterSynthesizedWrapper(D)) {
933+
auto *Importer = static_cast<ClangImporter *>(Ctx.getClangModuleLoader());
934+
const ClangNode node = Importer->getEffectiveClangNode(D);
935+
if (!node.isNull()) {
936+
if (auto named = dyn_cast_or_null<clang::NamedDecl>(node.getAsDecl())) {
937+
if (const auto imported = Importer->importDeclCached(named)) {
938+
if (imported && imported.has_value()) {
939+
if (ValueDecl *VD =
940+
dyn_cast_or_null<ValueDecl>(imported.value())) {
941+
D = VD;
942+
}
943+
}
944+
}
945+
}
946+
}
947+
}
948+
904949
if (auto *GenParam = dyn_cast<GenericTypeParamDecl>(D)) {
905950
D = canonicalizeGenericTypeParamDeclForIndex(GenParam);
906951
}

test/Index/index_imported_objc.swift

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,18 @@
2121
@property int categoryAddedProperty;
2222
@end
2323
24+
extern NSErrorDomain const TestErrorDomain;
25+
26+
typedef NS_ERROR_ENUM(TestErrorDomain, TestError){
27+
TestErrorFoo = 0,
28+
TestErrorBar = 1,
29+
};
30+
31+
typedef NS_ENUM(NSInteger, ErrCategory) {
32+
ErrCategoryA = 0,
33+
ErrCategoryB = 1,
34+
};
35+
2436
//--- module.modulemap
2537
module objc_decls {
2638
header "objc_decls.h"
@@ -48,3 +60,34 @@ class SubObjCClass: ObjCClass {
4860
// CHECK-NEXT: RelOver | instance-method/Swift | protocolAddedMethod() | c:objc(pl)MemberAdding(im)protocolAddedMethod
4961
// CHECK-NEXT: RelChild | class/Swift | SubObjCClass | c:@M@swift_ide_test@objc(cs)SubObjCClass
5062
}
63+
func testEnumIndex() {
64+
let _: TestError.Code = .bar
65+
// CHECK: [[@LINE-1]]:10 | enum/Swift | Code | c:@E@TestError | Ref | rel: 0
66+
// CHECK: [[@LINE-2]]:20 | enum/Swift | Code | c:@E@TestError | Ref,RelCont | rel: 1
67+
// CHECK: [[@LINE-3]]:28 | enumerator/Swift | bar | c:@E@TestError@TestErrorBar | Ref,RelCont | rel: 1
68+
let e = TestError.foo
69+
// CHECK: [[@LINE-1]]:11 | enum/Swift | Code | c:@E@TestError | Ref,RelCont | rel: 1
70+
// CHECK: [[@LINE-2]]:21 | enumerator/Swift | foo | c:@E@TestError@TestErrorFoo | Ref,RelCont | rel: 1
71+
switch e {
72+
case TestError.foo: break
73+
// CHECK: [[@LINE-1]]:10 | enum/Swift | Code | c:@E@TestError | Ref,RelCont | rel: 1
74+
// CHECK: [[@LINE-2]]:20 | enumerator/Swift | foo | c:@E@TestError@TestErrorFoo | Ref,RelCont | rel: 1
75+
case .bar: break
76+
// CHECK: [[@LINE-1]]:11 | enumerator/Swift | bar | c:@E@TestError@TestErrorBar | Ref,RelCont | rel: 1
77+
default: break
78+
}
79+
let _ = ErrCategory.B
80+
// CHECK: [[@LINE-1]]:11 | enum/Swift | ErrCategory | c:@E@ErrCategory | Ref,RelCont | rel: 1
81+
// CHECK: [[@LINE-2]]:23 | enumerator/Swift | B | c:@E@ErrCategory@ErrCategoryB | Ref,RelCont | rel: 1
82+
let c: ErrCategory = .A
83+
// CHECK: [[@LINE-1]]:10 | enum/Swift | ErrCategory | c:@E@ErrCategory | Ref,RelCont | rel: 1
84+
// CHECK: [[@LINE-2]]:25 | enumerator/Swift | A | c:@E@ErrCategory@ErrCategoryA | Ref,RelCont | rel: 1
85+
switch c {
86+
case ErrCategory.A: break
87+
// CHECK: [[@LINE-1]]:22 | enumerator/Swift | A | c:@E@ErrCategory@ErrCategoryA | Ref,RelCont | rel: 1
88+
// CHECK: [[@LINE-2]]:10 | enum/Swift | ErrCategory | c:@E@ErrCategory | Ref,RelCont | rel: 1
89+
// CHECK: [[@LINE-3]]:22 | enum/Swift | ErrCategory | c:@E@ErrCategory | Ref,RelCont | rel: 1
90+
case .B: break
91+
// CHECK: [[@LINE-1]]:11 | enumerator/Swift | B | c:@E@ErrCategory@ErrCategoryB | Ref,RelCont | rel: 1
92+
}
93+
}

0 commit comments

Comments
 (0)