Skip to content

Commit ac448b8

Browse files
committed
[Clang importer] Don't cache swift_attr source files that have CustomAttrs with arguments
Since we can't do a proper "deep" clone of expression nodes, cloning such a CustomAttr is necessarily shallow. In such cases, don't cache the swift_attr source files at all, so we get fresh attribute nodes for each such usage.
1 parent 867cf28 commit ac448b8

File tree

5 files changed

+74
-18
lines changed

5 files changed

+74
-18
lines changed

lib/ClangImporter/ImportDecl.cpp

Lines changed: 56 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -8244,14 +8244,17 @@ bool importer::hasSameUnderlyingType(const clang::Type *a,
82448244

82458245
SourceFile &ClangImporter::Implementation::getClangSwiftAttrSourceFile(
82468246
ModuleDecl &module,
8247-
StringRef attributeText
8247+
StringRef attributeText,
8248+
bool cached
82488249
) {
8249-
auto &sourceFiles = ClangSwiftAttrSourceFiles[attributeText];
8250+
if (cached) {
8251+
auto &sourceFiles = ClangSwiftAttrSourceFiles[attributeText];
82508252

8251-
// Check whether we've already created a source file.
8252-
for (auto sourceFile : sourceFiles) {
8253-
if (sourceFile->getParentModule() == &module)
8254-
return *sourceFile;
8253+
// Check whether we've already created a source file.
8254+
for (auto sourceFile : sourceFiles) {
8255+
if (sourceFile->getParentModule() == &module)
8256+
return *sourceFile;
8257+
}
82558258
}
82568259

82578260
// Create a new buffer with a copy of the attribute text,
@@ -8273,7 +8276,11 @@ SourceFile &ClangImporter::Implementation::getClangSwiftAttrSourceFile(
82738276
// Create the source file.
82748277
auto sourceFile = new (SwiftContext)
82758278
SourceFile(module, SourceFileKind::Library, bufferID);
8276-
sourceFiles.push_back(sourceFile);
8279+
8280+
if (cached) {
8281+
auto &sourceFiles = ClangSwiftAttrSourceFiles[attributeText];
8282+
sourceFiles.push_back(sourceFile);
8283+
}
82778284

82788285
return *sourceFile;
82798286
}
@@ -8450,17 +8457,49 @@ ClangImporter::Implementation::importSwiftAttrAttributes(Decl *MappedDecl) {
84508457
continue;
84518458
}
84528459

8453-
// Dig out a source file we can use for parsing.
8454-
auto &sourceFile = getClangSwiftAttrSourceFile(
8455-
*MappedDecl->getDeclContext()->getParentModule(),
8456-
swiftAttr->getAttribute());
8460+
bool cached = true;
8461+
while (true) {
8462+
// Dig out a source file we can use for parsing.
8463+
auto &sourceFile = getClangSwiftAttrSourceFile(
8464+
*MappedDecl->getDeclContext()->getParentModule(),
8465+
swiftAttr->getAttribute(),
8466+
cached);
8467+
8468+
auto topLevelDecls = sourceFile.getTopLevelDecls();
8469+
8470+
// If we're using the cached version, check whether we can correctly
8471+
// clone the attribute.
8472+
if (cached) {
8473+
bool hasNonclonableAttribute = false;
8474+
for (auto decl : topLevelDecls) {
8475+
if (hasNonclonableAttribute)
8476+
break;
8477+
8478+
for (auto attr : decl->getAttrs()) {
8479+
if (auto customAttr = dyn_cast<CustomAttr>(attr)) {
8480+
if (customAttr->getArgs() != nullptr) {
8481+
hasNonclonableAttribute = true;
8482+
break;
8483+
}
8484+
}
8485+
}
8486+
}
84578487

8458-
// Collect the attributes from the synthesized top-level declaration in
8459-
// the source file.
8460-
auto topLevelDecls = sourceFile.getTopLevelDecls();
8461-
for (auto decl : topLevelDecls) {
8462-
for (auto attr : decl->getAttrs())
8463-
MappedDecl->getAttrs().add(attr->clone(SwiftContext));
8488+
if (hasNonclonableAttribute) {
8489+
cached = false;
8490+
continue;
8491+
}
8492+
}
8493+
8494+
// Collect the attributes from the synthesized top-level declaration in
8495+
// the source file.
8496+
for (auto decl : topLevelDecls) {
8497+
for (auto attr : decl->getAttrs()) {
8498+
MappedDecl->getAttrs().add(attr->clone(SwiftContext));
8499+
}
8500+
}
8501+
8502+
break;
84648503
}
84658504
}
84668505

lib/ClangImporter/ImporterImpl.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1057,7 +1057,8 @@ class LLVM_LIBRARY_VISIBILITY ClangImporter::Implementation
10571057

10581058
/// Retrieve the placeholder source file for use in parsing Swift attributes
10591059
/// in the given module.
1060-
SourceFile &getClangSwiftAttrSourceFile(ModuleDecl &module, StringRef attributeText);
1060+
SourceFile &getClangSwiftAttrSourceFile(
1061+
ModuleDecl &module, StringRef attributeText, bool cached);
10611062

10621063
/// Utility function to import Clang attributes from a source Swift decl to
10631064
/// synthesized Swift decl.

test/Inputs/clang-importer-sdk/usr/include/completion_handler_globals.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
#if __SWIFT_ATTR_SUPPORTS_MACROS
22
#define ADD_ASYNC __attribute__((swift_attr("@macro_library.AddAsync")))
33
#define ADD_ASYNC_FINAL __attribute__((swift_attr("@macro_library.AddAsyncFinal")))
4+
#define DO_SOMETHING_DOTTED __attribute__((swift_attr("@AcceptDotted(.something)")))
45
#else
56
#define ADD_ASYNC
67
#define ADD_ASYNC_FINAL
8+
#define DO_SOMETHING_DOTTED
79
#endif
810

911
void async_divide(double x, double y, void (^ _Nonnull completionHandler)(double x)) ADD_ASYNC;
@@ -15,6 +17,9 @@ void computer_divide(const SlowComputer *computer, double x, double y, void (^ _
1517
ADD_ASYNC
1618
__attribute__((swift_name("SlowComputer.divide(self:_:_:completionHandler:)")));
1719

20+
void f1(double x) DO_SOMETHING_DOTTED;
21+
void f2(double x) DO_SOMETHING_DOTTED;
22+
void f3(double x) DO_SOMETHING_DOTTED;
1823

1924
#if __OBJC__
2025
@import Foundation;

test/Macros/Inputs/macro_library.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,3 +59,10 @@ public macro AddAsync() = #externalMacro(module: "MacroDefinition", type: "AddAs
5959

6060
@attached(peer, names: overloaded)
6161
public macro AddAsyncFinal() = #externalMacro(module: "MacroDefinition", type: "AddAsyncMacro")
62+
63+
public enum Something {
64+
case something
65+
}
66+
67+
@attached(peer, names: overloaded)
68+
public macro AcceptedDotted(_: Something) = #externalMacro(module: "MacroDefinition", type: "EmptyPeerMacro")

test/Macros/expand_on_imported.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@ import macro_library
2020
func testAll(x: Double, y: Double, computer: SlowComputer) async {
2121
let _: Double = await async_divide(1.0, 2.0)
2222
let _: Double = await computer.divide(x, y)
23+
24+
f1(3.14159)
25+
f2(3.14159)
26+
f3(3.14159)
2327
}
2428

2529
// CHECK: define{{.*}}@"$sSC12async_divideyS2d_SdtYaF"

0 commit comments

Comments
 (0)