Skip to content

Commit 0c91a34

Browse files
committed
Formalize the notion of "can clone" so we don't try to clone an attribute that won't work
1 parent ac448b8 commit 0c91a34

File tree

3 files changed

+31
-9
lines changed

3 files changed

+31
-9
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: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8476,26 +8476,29 @@ ClangImporter::Implementation::importSwiftAttrAttributes(Decl *MappedDecl) {
84768476
break;
84778477

84788478
for (auto attr : decl->getAttrs()) {
8479-
if (auto customAttr = dyn_cast<CustomAttr>(attr)) {
8480-
if (customAttr->getArgs() != nullptr) {
8481-
hasNonclonableAttribute = true;
8482-
break;
8483-
}
8479+
if (!attr->canClone()) {
8480+
hasNonclonableAttribute = true;
8481+
break;
84848482
}
84858483
}
84868484
}
84878485

8486+
// We cannot clone one of the attributes. Go back and build a new
8487+
// source file without caching it.
84888488
if (hasNonclonableAttribute) {
84898489
cached = false;
84908490
continue;
84918491
}
84928492
}
84938493

84948494
// Collect the attributes from the synthesized top-level declaration in
8495-
// the source file.
8495+
// the source file. If we're using a cached copy, clone the attribute.
84968496
for (auto decl : topLevelDecls) {
8497-
for (auto attr : decl->getAttrs()) {
8498-
MappedDecl->getAttrs().add(attr->clone(SwiftContext));
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);
84998502
}
85008503
}
85018504

0 commit comments

Comments
 (0)