Skip to content

Commit 1d30654

Browse files
committed
ClangImporter: Record the error wrapper's struct 'Code' member enum in a side table
1 parent 3b6e3b1 commit 1d30654

File tree

7 files changed

+48
-50
lines changed

7 files changed

+48
-50
lines changed

include/swift/AST/ClangModuleLoader.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ class Sema;
2525
namespace swift {
2626

2727
class DeclContext;
28+
class EnumDecl;
29+
class StructDecl;
2830
class VisibleDeclConsumer;
2931

3032
/// Represents the different namespaces for types in C.
@@ -77,6 +79,9 @@ class ClangModuleLoader : public ModuleLoader {
7779
/// \param name The name we're searching for.
7880
virtual void lookupValue(DeclName name, VisibleDeclConsumer &consumer) = 0;
7981

82+
/// Look up the nested 'Code' enum for an error wrapper struct.
83+
virtual EnumDecl *lookupErrorCodeEnum(const StructDecl *errorWrapper) = 0;
84+
8085
/// Look up a type declaration by its Clang name.
8186
///
8287
/// Note that this method does no filtering. If it finds the type in a loaded

include/swift/ClangImporter/ClangImporter.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,9 @@ class ClangImporter final : public ClangModuleLoader {
192192
/// \param name The name we're searching for.
193193
void lookupValue(DeclName name, VisibleDeclConsumer &consumer) override;
194194

195+
/// Look up the nested 'Code' enum for an error wrapper struct.
196+
EnumDecl *lookupErrorCodeEnum(const StructDecl *errorWrapper) override;
197+
195198
/// Look up a type declaration by its Clang name.
196199
///
197200
/// Note that this method does no filtering. If it finds the type in a loaded

lib/ClangImporter/ClangImporter.cpp

Lines changed: 14 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -2171,21 +2171,10 @@ static bool isVisibleFromModule(const ClangModuleUnit *ModuleFilter,
21712171
case ClangImporterSynthesizedTypeAttr::Kind::NSErrorWrapper:
21722172
case ClangImporterSynthesizedTypeAttr::Kind::NSErrorWrapperAnon: {
21732173
ASTContext &Ctx = ContainingUnit->getASTContext();
2174-
auto LookupFlags =
2175-
NominalTypeDecl::LookupDirectFlags::IgnoreNewExtensions;
2174+
auto *Importer = Ctx.getClangModuleLoader();
21762175
auto WrapperStruct = cast<StructDecl>(VD);
2177-
TinyPtrVector<ValueDecl *> LookupResults =
2178-
WrapperStruct->lookupDirect(Ctx.Id_Code, LookupFlags);
2179-
assert(!LookupResults.empty() && "imported error enum without Code");
2180-
2181-
auto CodeEnumIter = llvm::find_if(LookupResults,
2182-
[&](ValueDecl *Member) -> bool {
2183-
return Member->getDeclContext() == WrapperStruct;
2184-
});
2185-
assert(CodeEnumIter != LookupResults.end() &&
2186-
"could not find Code enum in wrapper struct");
2187-
assert((*CodeEnumIter)->hasClangNode());
2188-
ClangNode = (*CodeEnumIter)->getClangNode();
2176+
auto *CodeEnum = Importer->lookupErrorCodeEnum(WrapperStruct);
2177+
ClangNode = CodeEnum->getClangNode();
21892178
break;
21902179
}
21912180
}
@@ -2496,6 +2485,10 @@ void ClangImporter::lookupValue(DeclName name, VisibleDeclConsumer &consumer) {
24962485
});
24972486
}
24982487

2488+
EnumDecl *ClangImporter::lookupErrorCodeEnum(const StructDecl *errorWrapper) {
2489+
return Impl.lookupErrorCodeEnum(errorWrapper);
2490+
}
2491+
24992492
void ClangImporter::lookupTypeDecl(
25002493
StringRef rawName, ClangTypeKind kind,
25012494
llvm::function_ref<void(TypeDecl *)> receiver) {
@@ -2794,20 +2787,13 @@ ClangModuleUnit::lookupNestedType(Identifier name,
27942787
const NominalTypeDecl *baseType) const {
27952788
// Special case for error code enums: try looking directly into the struct
27962789
// first. But only if it looks like a synthesized error wrapped struct.
2797-
if (name == getASTContext().Id_Code && !baseType->hasClangNode() &&
2798-
isa<StructDecl>(baseType) && !baseType->hasLazyMembers() &&
2799-
baseType->isChildContextOf(this)) {
2800-
auto *mutableBase = const_cast<NominalTypeDecl *>(baseType);
2801-
auto flags = OptionSet<NominalTypeDecl::LookupDirectFlags>();
2802-
flags |= NominalTypeDecl::LookupDirectFlags::IgnoreNewExtensions;
2803-
auto codeEnum = mutableBase->lookupDirect(name, flags);
2804-
// Double-check that we actually have a good result. It's possible what we
2805-
// found is /not/ a synthesized error struct, but just something that looks
2806-
// like it. But if we still found a good result we should return that.
2807-
if (codeEnum.size() == 1 && isa<TypeDecl>(codeEnum.front()))
2808-
return cast<TypeDecl>(codeEnum.front());
2809-
if (codeEnum.size() > 1)
2810-
return nullptr;
2790+
if (name == getASTContext().Id_Code &&
2791+
!baseType->hasClangNode() &&
2792+
isa<StructDecl>(baseType)) {
2793+
auto *wrapperStruct = cast<StructDecl>(baseType);
2794+
if (auto *codeEnum = owner.lookupErrorCodeEnum(wrapperStruct))
2795+
return codeEnum;
2796+
28112797
// Otherwise, fall back and try via lookup table.
28122798
}
28132799

lib/ClangImporter/ImportDecl.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2948,6 +2948,9 @@ namespace {
29482948
// Add the 'Code' enum to the error wrapper.
29492949
errorWrapper->addMember(enumDecl);
29502950
Impl.addAlternateDecl(enumDecl, errorWrapper);
2951+
2952+
// Stash the 'Code' enum so we can find it later.
2953+
Impl.ErrorCodeEnums[errorWrapper] = enumDecl;
29512954
}
29522955

29532956
// The enumerators go into this enumeration.

lib/ClangImporter/ImportType.cpp

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -821,23 +821,15 @@ namespace {
821821

822822
/// Retrieve the 'Code' type for a bridged NSError, or nullptr if
823823
/// this is not a bridged NSError type.
824-
static TypeDecl *getBridgedNSErrorCode(TypeDecl *decl) {
825-
auto nominal = dyn_cast<NominalTypeDecl>(decl);
826-
if (!nominal) return nullptr;
824+
TypeDecl *getBridgedNSErrorCode(TypeDecl *decl) {
825+
auto errorWrapper = dyn_cast<StructDecl>(decl);
826+
if (!errorWrapper) return nullptr;
827827

828-
const DeclAttributes &allAttrs = decl->getAttrs();
828+
const DeclAttributes &allAttrs = errorWrapper->getAttrs();
829829
for (auto attr : allAttrs.getAttributes<SynthesizedProtocolAttr>()) {
830830
if (attr->getProtocolKind() ==
831831
KnownProtocolKind::BridgedStoredNSError) {
832-
auto &ctx = nominal->getASTContext();
833-
auto flags = OptionSet<NominalTypeDecl::LookupDirectFlags>();
834-
flags |= NominalTypeDecl::LookupDirectFlags::IgnoreNewExtensions;
835-
auto lookup = nominal->lookupDirect(ctx.Id_Code, flags);
836-
for (auto found : lookup) {
837-
if (auto codeDecl = dyn_cast<TypeDecl>(found))
838-
return codeDecl;
839-
}
840-
llvm_unreachable("couldn't find 'Code' within bridged error type");
832+
return Impl.lookupErrorCodeEnum(errorWrapper);
841833
}
842834
}
843835

lib/ClangImporter/ImporterImpl.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -498,6 +498,10 @@ class LLVM_LIBRARY_VISIBILITY ClangImporter::Implementation
498498
llvm::DenseMap<const NominalTypeDecl *, TinyPtrVector<ConstructorDecl *>>
499499
ConstructorsForNominal;
500500

501+
/// Keep track of the nested 'Code' enum for imported error wrapper
502+
/// structs.
503+
llvm::DenseMap<const StructDecl *, EnumDecl *> ErrorCodeEnums;
504+
501505
/// Retrieve the alternative declaration for the given imported
502506
/// Swift declaration.
503507
ArrayRef<ValueDecl *> getAlternateDecls(Decl *decl) {
@@ -1220,6 +1224,13 @@ class LLVM_LIBRARY_VISIBILITY ClangImporter::Implementation
12201224
return result;
12211225
}
12221226

1227+
EnumDecl *lookupErrorCodeEnum(const StructDecl *errorWrapper) {
1228+
auto found = ErrorCodeEnums.find(errorWrapper);
1229+
if (found == ErrorCodeEnums.end())
1230+
return nullptr;
1231+
return found->second;
1232+
}
1233+
12231234
virtual void
12241235
loadAllMembers(Decl *D, uint64_t unused) override;
12251236

lib/IDE/Utils.cpp

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -959,15 +959,13 @@ ClangNode swift::ide::getEffectiveClangNode(const Decl *decl) {
959959
return clangNode;
960960

961961
// Or via the nested "Code" enum.
962-
if (auto nominal =
963-
const_cast<NominalTypeDecl *>(dyn_cast<NominalTypeDecl>(decl))) {
964-
auto &ctx = nominal->getASTContext();
965-
auto flags = OptionSet<NominalTypeDecl::LookupDirectFlags>();
966-
flags |= NominalTypeDecl::LookupDirectFlags::IgnoreNewExtensions;
967-
for (auto code : nominal->lookupDirect(ctx.Id_Code, flags)) {
968-
if (auto clangDecl = code->getClangDecl())
969-
return clangDecl;
970-
}
962+
if (auto *errorWrapper = dyn_cast<StructDecl>(decl)) {
963+
auto &ctx = errorWrapper->getASTContext();
964+
auto *loader = ctx.getClangModuleLoader();
965+
if (loader)
966+
if (auto *code = loader->lookupErrorCodeEnum(errorWrapper))
967+
if (auto clangDecl = code->getClangDecl())
968+
return clangDecl;
971969
}
972970

973971
return ClangNode();

0 commit comments

Comments
 (0)