Skip to content

Commit bea20a2

Browse files
committed
[cxx-interop] Check for NS_OPTIONS macro in findOptionSetEnum()
The NS_OPTIONS macro sometimes uses a pattern where it loosely associates a typedef with an anonymous enum via a shared underlying integer type (emphasis on "loosely"). The typedef is marked as unavailable in Swift so as to not cause name ambiguity when we associate the anonymous enum with said typedef. We use unavailability as a heuristic during the import process, but that conflates NS_OPTIONS with NS_ENUMs that can be marked as unavailable for entirely unrelated reasons. That in and of itself is fine, because the import logic is general enough to handle both cases, but we have an assertion that seems to be unaware of this scenario, and trips on unavailable NS_ENUMs. This patch adds an additional check to ensure what we think is an NS_OPTIONS type was defined with that particular macro. rdar://150399978
1 parent 75e4f04 commit bea20a2

File tree

4 files changed

+22
-20
lines changed

4 files changed

+22
-20
lines changed

lib/ClangImporter/ImportEnumInfo.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,11 @@ ImportedType importer::findOptionSetEnum(clang::QualType type,
255255
// then this definitely isn't used for {CF,NS}_OPTIONS.
256256
return ImportedType();
257257

258+
if (Impl.SwiftContext.LangOpts.EnableCXXInterop &&
259+
!isCFOptionsMacro(typedefType->getDecl(), Impl.getClangPreprocessor())) {
260+
return ImportedType();
261+
}
262+
258263
auto clangEnum = findAnonymousEnumForTypedef(Impl.SwiftContext, typedefType);
259264
if (!clangEnum)
260265
return ImportedType();

lib/ClangImporter/ImportEnumInfo.h

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919

2020
#include "swift/AST/ASTContext.h"
2121
#include "swift/AST/Decl.h"
22+
#include "clang/Lex/Preprocessor.h"
23+
#include "clang/Sema/Sema.h"
2224
#include "llvm/ADT/APSInt.h"
2325
#include "llvm/ADT/DenseMap.h"
2426

@@ -164,14 +166,18 @@ StringRef getCommonPluralPrefix(StringRef singular, StringRef plural);
164166
/// an elaborated type, an unwrapped type is returned.
165167
const clang::Type *getUnderlyingType(const clang::EnumDecl *decl);
166168

167-
inline bool isCFOptionsMacro(StringRef macroName) {
168-
return llvm::StringSwitch<bool>(macroName)
169+
inline bool isCFOptionsMacro(const clang::NamedDecl *decl,
170+
clang::Preprocessor &preprocessor) {
171+
auto loc = decl->getEndLoc();
172+
if (!loc.isMacroID())
173+
return false;
174+
return llvm::StringSwitch<bool>(preprocessor.getImmediateMacroName(loc))
169175
.Case("CF_OPTIONS", true)
170176
.Case("NS_OPTIONS", true)
171177
.Default(false);
172178
}
173179

174-
}
175-
}
180+
} // namespace importer
181+
} // namespace swift
176182

177183
#endif // SWIFT_CLANG_IMPORT_ENUM_H

lib/ClangImporter/ImportName.cpp

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "CFTypeInfo.h"
1919
#include "ClangClassTemplateNamePrinter.h"
2020
#include "ClangDiagnosticConsumer.h"
21+
#include "ImportEnumInfo.h"
2122
#include "ImporterImpl.h"
2223
#include "swift/AST/ASTContext.h"
2324
#include "swift/AST/ClangSwiftTypeCorrespondence.h"
@@ -1877,15 +1878,9 @@ ImportedName NameImporter::importNameImpl(const clang::NamedDecl *D,
18771878
// imported into Swift to avoid having two types with the same name, which
18781879
// cause subtle name lookup issues.
18791880
if (swiftCtx.LangOpts.EnableCXXInterop &&
1880-
isUnavailableInSwift(D, nullptr, true)) {
1881-
auto loc = D->getEndLoc();
1882-
if (loc.isMacroID()) {
1883-
StringRef macroName =
1884-
clangSema.getPreprocessor().getImmediateMacroName(loc);
1885-
if (isCFOptionsMacro(macroName))
1886-
return ImportedName();
1887-
}
1888-
}
1881+
isUnavailableInSwift(D, nullptr, true) &&
1882+
isCFOptionsMacro(D, clangSema.getPreprocessor()))
1883+
return ImportedName();
18891884

18901885
/// Whether the result is a function name.
18911886
bool isFunction = false;

lib/ClangImporter/ImportType.cpp

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
//===----------------------------------------------------------------------===//
1616

1717
#include "CFTypeInfo.h"
18+
#include "ImportEnumInfo.h"
1819
#include "ImporterImpl.h"
1920
#include "SwiftDeclSynthesizer.h"
2021
#include "swift/ABI/MetadataValues.h"
@@ -2909,13 +2910,8 @@ ArgumentAttrs ClangImporter::Implementation::inferDefaultArgument(
29092910
return argumentAttrs;
29102911
}
29112912
}
2912-
auto loc = typedefDecl->getEndLoc();
2913-
if (loc.isMacroID()) {
2914-
StringRef macroName =
2915-
nameImporter.getClangPreprocessor().getImmediateMacroName(loc);
2916-
if (isCFOptionsMacro(macroName))
2917-
return argumentAttrs;
2918-
}
2913+
if (isCFOptionsMacro(typedefDecl, nameImporter.getClangPreprocessor()))
2914+
return argumentAttrs;
29192915
}
29202916
}
29212917

0 commit comments

Comments
 (0)