Skip to content

Commit 41efe32

Browse files
authored
Merge pull request #77962 from DougGregor/importer-no-cache-custom-swift-attr
[Clang importer] Don't cache swift_attr source files that have CustomAttrs with arguments
2 parents 4822920 + 0c91a34 commit 41efe32

File tree

7 files changed

+97
-19
lines changed

7 files changed

+97
-19
lines changed

include/swift/AST/Attr.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -508,13 +508,17 @@ class DeclAttribute : public AttributeBase {
508508

509509
/// Create a copy of this attribute.
510510
DeclAttribute *clone(ASTContext &ctx) const;
511+
512+
/// Determine whether we can clone this attribute.
513+
bool canClone() const;
511514
};
512515

513516
#define UNIMPLEMENTED_CLONE(AttrType) \
514517
AttrType *clone(ASTContext &ctx) const { \
515518
llvm_unreachable("unimplemented"); \
516519
return nullptr; \
517-
}
520+
} \
521+
bool canClone() const { return false; }
518522

519523
/// Describes a "simple" declaration attribute that carries no data.
520524
template<DeclAttrKind Kind>
@@ -1916,9 +1920,13 @@ class CustomAttr final : public DeclAttribute {
19161920

19171921
/// Create a copy of this attribute.
19181922
CustomAttr *clone(ASTContext &ctx) const {
1923+
assert(argList == nullptr &&
1924+
"Cannot clone custom attribute with an argument list");
19191925
return create(ctx, AtLoc, getTypeExpr(), initContext, argList, isImplicit());
19201926
}
19211927

1928+
bool canClone() const { return argList == nullptr; }
1929+
19221930
private:
19231931
friend class CustomAttrNominalRequest;
19241932
void resetTypeInformation(TypeExpr *repr);

lib/AST/Attr.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,17 @@ DeclAttribute *DeclAttribute::clone(ASTContext &ctx) const {
370370
}
371371
}
372372

373+
bool DeclAttribute::canClone() const {
374+
switch (getKind()) {
375+
#define DECL_ATTR(_,CLASS, ...) \
376+
case DeclAttrKind::CLASS: \
377+
if (&CLASS##Attr::canClone == &DeclAttribute::canClone) \
378+
return true; \
379+
return static_cast<const CLASS##Attr *>(this)->canClone();
380+
#include "swift/AST/DeclAttr.def"
381+
}
382+
}
383+
373384
const BackDeployedAttr *
374385
DeclAttributes::getBackDeployed(const ASTContext &ctx,
375386
bool forTargetVariant) const {

lib/ClangImporter/ImportDecl.cpp

Lines changed: 59 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,52 @@ 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 (!attr->canClone()) {
8480+
hasNonclonableAttribute = true;
8481+
break;
8482+
}
8483+
}
8484+
}
8485+
8486+
// We cannot clone one of the attributes. Go back and build a new
8487+
// source file without caching it.
8488+
if (hasNonclonableAttribute) {
8489+
cached = false;
8490+
continue;
8491+
}
8492+
}
84578493

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));
8494+
// Collect the attributes from the synthesized top-level declaration in
8495+
// the source file. If we're using a cached copy, clone the attribute.
8496+
for (auto decl : topLevelDecls) {
8497+
SmallVector<DeclAttribute *, 2> attrs(decl->getAttrs().begin(),
8498+
decl->getAttrs().end());
8499+
for (auto attr : attrs) {
8500+
MappedDecl->getAttrs().add(cached ? attr->clone(SwiftContext)
8501+
: attr);
8502+
}
8503+
}
8504+
8505+
break;
84648506
}
84658507
}
84668508

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)