Skip to content

Commit f96c910

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

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
@@ -504,13 +504,17 @@ class DeclAttribute : public AttributeBase {
504504

505505
/// Create a copy of this attribute.
506506
DeclAttribute *clone(ASTContext &ctx) const;
507+
508+
/// Determine whether we can clone this attribute.
509+
bool canClone() const;
507510
};
508511

509512
#define UNIMPLEMENTED_CLONE(AttrType) \
510513
AttrType *clone(ASTContext &ctx) const { \
511514
llvm_unreachable("unimplemented"); \
512515
return nullptr; \
513-
}
516+
} \
517+
bool canClone() const { return false; }
514518

515519
/// Describes a "simple" declaration attribute that carries no data.
516520
template<DeclAttrKind Kind>
@@ -1908,9 +1912,13 @@ class CustomAttr final : public DeclAttribute {
19081912

19091913
/// Create a copy of this attribute.
19101914
CustomAttr *clone(ASTContext &ctx) const {
1915+
assert(argList == nullptr &&
1916+
"Cannot clone custom attribute with an argument list");
19111917
return create(ctx, AtLoc, getTypeExpr(), initContext, argList, isImplicit());
19121918
}
19131919

1920+
bool canClone() const { return argList == nullptr; }
1921+
19141922
private:
19151923
friend class CustomAttrNominalRequest;
19161924
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
bool
374385
DeclAttributes::isUnavailableInSwiftVersion(
375386
const version::Version &effectiveVersion) const {

lib/ClangImporter/ImportDecl.cpp

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8437,26 +8437,29 @@ ClangImporter::Implementation::importSwiftAttrAttributes(Decl *MappedDecl) {
84378437
break;
84388438

84398439
for (auto attr : decl->getAttrs()) {
8440-
if (auto customAttr = dyn_cast<CustomAttr>(attr)) {
8441-
if (customAttr->getArgs() != nullptr) {
8442-
hasNonclonableAttribute = true;
8443-
break;
8444-
}
8440+
if (!attr->canClone()) {
8441+
hasNonclonableAttribute = true;
8442+
break;
84458443
}
84468444
}
84478445
}
84488446

8447+
// We cannot clone one of the attributes. Go back and build a new
8448+
// source file without caching it.
84498449
if (hasNonclonableAttribute) {
84508450
cached = false;
84518451
continue;
84528452
}
84538453
}
84548454

84558455
// Collect the attributes from the synthesized top-level declaration in
8456-
// the source file.
8456+
// the source file. If we're using a cached copy, clone the attribute.
84578457
for (auto decl : topLevelDecls) {
8458-
for (auto attr : decl->getAttrs()) {
8459-
MappedDecl->getAttrs().add(attr->clone(SwiftContext));
8458+
SmallVector<DeclAttribute *, 2> attrs(decl->getAttrs().begin(),
8459+
decl->getAttrs().end());
8460+
for (auto attr : attrs) {
8461+
MappedDecl->getAttrs().add(cached ? attr->clone(SwiftContext)
8462+
: attr);
84608463
}
84618464
}
84628465

0 commit comments

Comments
 (0)