Merge pull request #10965 from ahoppen/deinit-special-name

This commit is contained in:
swift-ci
2017-08-01 07:50:00 -07:00
committed by GitHub
26 changed files with 117 additions and 49 deletions
+6 -4
View File
@@ -4866,8 +4866,6 @@ protected:
}
public:
Identifier getName() const { return getFullName().getBaseIdentifier(); }
/// Returns the string for the base name, or "_" if this is unnamed.
StringRef getNameStr() const {
assert(!getFullName().isSpecial() && "Cannot get string for special names");
@@ -5200,6 +5198,8 @@ public:
TypeLoc FnRetType, DeclContext *Parent,
ClangNode ClangN = ClangNode());
Identifier getName() const { return getFullName().getBaseIdentifier(); }
bool isStatic() const {
return FuncDeclBits.IsStatic;
}
@@ -5648,6 +5648,8 @@ public:
GenericParamList *GenericParams,
DeclContext *Parent);
Identifier getName() const { return getFullName().getBaseIdentifier(); }
void setParameterLists(ParamDecl *selfParam, ParameterList *bodyParams);
SourceLoc getConstructorLoc() const { return getNameLoc(); }
@@ -5839,8 +5841,8 @@ public:
class DestructorDecl : public AbstractFunctionDecl {
ParameterList *SelfParameter;
public:
DestructorDecl(Identifier NameHack, SourceLoc DestructorLoc,
ParamDecl *selfDecl, DeclContext *Parent);
DestructorDecl(SourceLoc DestructorLoc, ParamDecl *selfDecl,
DeclContext *Parent);
void setSelfDecl(ParamDecl *selfDecl);
+12 -1
View File
@@ -214,7 +214,8 @@ class DeclBaseName {
public:
enum class Kind: uint8_t {
Normal,
Subscript
Subscript,
Destructor
};
private:
@@ -223,6 +224,8 @@ private:
/// This is an implementation detail that should never leak outside of
/// DeclName.
static void *SubscriptIdentifierData;
/// As above, for special destructor DeclNames.
static void *DestructorIdentifierData;
Identifier Ident;
@@ -235,9 +238,15 @@ public:
return DeclBaseName(Identifier((const char *)SubscriptIdentifierData));
}
static DeclBaseName createDestructor() {
return DeclBaseName(Identifier((const char *)DestructorIdentifierData));
}
Kind getKind() const {
if (Ident.get() == SubscriptIdentifierData) {
return Kind::Subscript;
} else if (Ident.get() == DestructorIdentifierData) {
return Kind::Destructor;
} else {
return Kind::Normal;
}
@@ -273,6 +282,8 @@ public:
return getIdentifier().str();
case Kind::Subscript:
return "subscript";
case Kind::Destructor:
return "deinit";
}
}
-1
View File
@@ -43,7 +43,6 @@ IDENTIFIER(decode)
IDENTIFIER(decodeIfPresent)
IDENTIFIER(Decoder)
IDENTIFIER(decoder)
IDENTIFIER(deinit)
IDENTIFIER(Element)
IDENTIFIER(Encodable)
IDENTIFIER(encode)
+5 -2
View File
@@ -54,7 +54,7 @@ const uint16_t VERSION_MAJOR = 0;
/// in source control, you should also update the comment to briefly
/// describe what change you made. The content of this comment isn't important;
/// it just ensures a conflict if two people change the module format.
const uint16_t VERSION_MINOR = 353; // Last change: count inherited conformances
const uint16_t VERSION_MINOR = 354; // Last change: special destructor names
using DeclID = PointerEmbeddedInt<unsigned, 31>;
using DeclIDField = BCFixed<31>;
@@ -345,7 +345,8 @@ using OptionalTypeKindField = BCFixed<2>;
// VERSION_MAJOR.
enum class DeclNameKind: uint8_t {
Normal,
Subscript
Subscript,
Destructor
};
// These IDs must \em not be renumbered or reordered without incrementing
@@ -359,6 +360,8 @@ enum SpecialIdentifierID : uint8_t {
OBJC_HEADER_MODULE_ID,
/// Special value for the special subscript name
SUBSCRIPT_ID,
/// Special value for the special destructor name
DESTRUCTOR_ID,
/// The number of special Identifier IDs. This value should never be encoded;
/// it should only be used to count the number of names above. As such, it
+2
View File
@@ -548,6 +548,8 @@ void ASTMangler::appendDeclName(const ValueDecl *decl) {
case DeclBaseName::Kind::Subscript:
appendIdentifier("subscript");
break;
case DeclBaseName::Kind::Destructor:
llvm_unreachable("Destructors are not mangled using appendDeclName");
}
} else {
assert(AllowNamelessEntities && "attempt to mangle unnamed decl");
+20 -12
View File
@@ -420,7 +420,7 @@ bool Decl::isPrivateStdlibDecl(bool whitelistProtocols) const {
if (auto AFD = dyn_cast<AbstractFunctionDecl>(D)) {
// Hide '~>' functions (but show the operator, because it defines
// precedence).
if (AFD->getNameStr() == "~>")
if (isa<FuncDecl>(AFD) && AFD->getNameStr() == "~>")
return true;
// If it's a function with a parameter with leading underscore, it's a
@@ -2557,8 +2557,7 @@ ClassDecl::ClassDecl(SourceLoc ClassLoc, Identifier Name, SourceLoc NameLoc,
}
DestructorDecl *ClassDecl::getDestructor() {
auto name = getASTContext().Id_deinit;
auto results = lookupDirect(name);
auto results = lookupDirect(DeclBaseName::createDestructor());
assert(!results.empty() && "Class without destructor?");
assert(results.size() == 1 && "More than one destructor?");
return cast<DestructorDecl>(results.front());
@@ -4572,7 +4571,20 @@ ObjCSelector AbstractFunctionDecl::getObjCSelector(
}
auto &ctx = getASTContext();
auto baseName = getName();
Identifier baseName;
if (isa<DestructorDecl>(this)) {
// Deinitializers are always called "dealloc".
return ObjCSelector(ctx, 0, ctx.Id_dealloc);
} else if (auto func = dyn_cast<FuncDecl>(this)) {
// Otherwise cast this to be able to access getName()
baseName = func->getName();
} else if (auto ctor = dyn_cast<ConstructorDecl>(this)) {
baseName = ctor->getName();
} else {
llvm_unreachable("Unknown subclass of AbstractFunctionDecl");
}
auto argNames = getFullName().getArgumentNames();
// Use the preferred name if specified
@@ -4596,11 +4608,6 @@ ObjCSelector AbstractFunctionDecl::getObjCSelector(
}
}
// Deinitializers are always called "dealloc".
if (isa<DestructorDecl>(this)) {
return ObjCSelector(ctx, 0, ctx.Id_dealloc);
}
// If this is a zero-parameter initializer with a long selector
// name, form that selector.
@@ -4960,9 +4967,10 @@ bool ConstructorDecl::isObjCZeroParameterWithLongSelector() const {
return params->get(0)->getInterfaceType()->isVoid();
}
DestructorDecl::DestructorDecl(Identifier NameHack, SourceLoc DestructorLoc,
ParamDecl *selfDecl, DeclContext *Parent)
: AbstractFunctionDecl(DeclKind::Destructor, Parent, NameHack, DestructorLoc,
DestructorDecl::DestructorDecl(SourceLoc DestructorLoc, ParamDecl *selfDecl,
DeclContext *Parent)
: AbstractFunctionDecl(DeclKind::Destructor, Parent,
DeclBaseName::createDestructor(), DestructorLoc,
/*Throws=*/false, /*ThrowsLoc=*/SourceLoc(),
/*NumParameterLists=*/1, nullptr) {
setSelfDecl(selfDecl);
+1 -1
View File
@@ -806,7 +806,7 @@ unsigned DeclContext::printContext(raw_ostream &OS, unsigned indent) const {
break;
case DeclContextKind::AbstractFunctionDecl: {
auto *AFD = cast<AbstractFunctionDecl>(this);
OS << " name=" << AFD->getName();
OS << " name=" << AFD->getFullName();
if (AFD->hasInterfaceType())
OS << " : " << AFD->getInterfaceType();
else
+2
View File
@@ -22,6 +22,8 @@ using namespace swift;
void *DeclBaseName::SubscriptIdentifierData =
&DeclBaseName::SubscriptIdentifierData;
void *DeclBaseName::DestructorIdentifierData =
&DeclBaseName::DestructorIdentifierData;
raw_ostream &llvm::operator<<(raw_ostream &OS, Identifier I) {
if (I.get() == nullptr)
+5
View File
@@ -211,6 +211,8 @@ DeclBaseName SerializedSwiftName::toDeclBaseName(ASTContext &Context) const {
return Context.getIdentifier(Name);
case DeclBaseName::Kind::Subscript:
return DeclBaseName::createSubscript();
case DeclBaseName::Kind::Destructor:
return DeclBaseName::createDestructor();
}
}
@@ -829,6 +831,9 @@ void SwiftLookupTable::dump() const {
case DeclBaseName::Kind::Subscript:
llvm::errs() << " subscript:\n";
break;
case DeclBaseName::Kind::Destructor:
llvm::errs() << " deinit:\n";
break;
}
const auto &entries = LookupTable.find(baseName)->second;
for (const auto &entry : entries) {
+2
View File
@@ -82,6 +82,8 @@ struct SerializedSwiftName {
return Name;
case DeclBaseName::Kind::Subscript:
return "subscript";
case DeclBaseName::Kind::Destructor:
return "deinit";
}
}
+2 -2
View File
@@ -5792,8 +5792,8 @@ parseDeclDeinit(ParseDeclOptions Flags, DeclAttributes &Attributes) {
auto *SelfDecl = ParamDecl::createUnboundSelf(DestructorLoc, CurDeclContext);
Scope S(this, ScopeKind::DestructorBody);
auto *DD = new (Context) DestructorDecl(Context.Id_deinit, DestructorLoc,
SelfDecl, CurDeclContext);
auto *DD = new (Context) DestructorDecl(DestructorLoc, SelfDecl,
CurDeclContext);
// Parse the body.
if (Tok.is(tok::l_brace)) {
+4 -3
View File
@@ -434,9 +434,6 @@ bool SILParser::parseSILIdentifier(Identifier &Result, SourceLoc &Loc,
// A binary operator can be part of a SILDeclRef.
Result = P.Context.getIdentifier(P.Tok.getText());
break;
case tok::kw_deinit:
Result = P.Context.Id_deinit;
break;
case tok::kw_init:
Result = P.Context.Id_init;
break;
@@ -1148,6 +1145,10 @@ bool SILParser::parseSILDottedPathWithoutPound(ValueDecl *&Decl,
P.consumeToken();
FullName.push_back(DeclBaseName::createSubscript());
break;
case tok::kw_deinit:
P.consumeToken();
FullName.push_back(DeclBaseName::createDestructor());
break;
default:
if (parseSILIdentifier(Id, diag::expected_sil_constant))
return true;
+2
View File
@@ -1626,6 +1626,8 @@ static SelectorFamily getSelectorFamily(SILDeclRef c) {
return getSelectorFamily(declName.getIdentifier());
case DeclBaseName::Kind::Subscript:
return SelectorFamily::None;
case DeclBaseName::Kind::Destructor:
return SelectorFamily::None;
}
}
return SelectorFamily::None;
+2 -1
View File
@@ -239,7 +239,8 @@ static void printValueDecl(ValueDecl *Decl, raw_ostream &OS) {
if (Decl->isOperator()) {
OS << '"' << Decl->getBaseName() << '"';
} else if (Decl->getBaseName() == "subscript") {
} else if (Decl->getBaseName() == "subscript" ||
Decl->getBaseName() == "deinit") {
OS << '`' << Decl->getBaseName() << '`';
} else {
OS << Decl->getBaseName();
+3 -4
View File
@@ -2532,6 +2532,9 @@ diagnoseUnviableLookupResults(MemberLookupResult &result, Type baseObjTy,
if (memberName.getBaseName().getKind() == DeclBaseName::Kind::Subscript) {
diagnose(loc, diag::type_not_subscriptable, baseObjTy)
.highlight(baseRange);
} else if (memberName.getBaseName() == "deinit") {
// Specialised diagnostic if trying to access deinitialisers
diagnose(loc, diag::destructor_not_accessible).highlight(baseRange);
} else if (auto metatypeTy = baseObjTy->getAs<MetatypeType>()) {
auto instanceTy = metatypeTy->getInstanceType();
tryTypoCorrection();
@@ -2691,10 +2694,6 @@ diagnoseUnviableLookupResults(MemberLookupResult &result, Type baseObjTy,
return;
}
case MemberLookupResult::UR_DestructorInaccessible: {
diagnose(nameLoc, diag::destructor_not_accessible);
return;
}
}
}
-5
View File
@@ -3206,11 +3206,6 @@ performMemberLookup(ConstraintKind constraintKind, DeclName memberName,
// reasonable choice.
auto addChoice = [&](ValueDecl *cand, bool isBridged,
bool isUnwrappedOptional) {
// Destructors cannot be referenced manually
if (isa<DestructorDecl>(cand)) {
result.addUnviable(cand, MemberLookupResult::UR_DestructorInaccessible);
return;
}
// If the result is invalid, skip it.
TC.validateDecl(cand);
if (cand->isInvalid()) {
+1 -2
View File
@@ -2185,8 +2185,7 @@ void TypeChecker::addImplicitDestructor(ClassDecl *CD) {
auto *selfDecl = ParamDecl::createSelf(CD->getLoc(), CD);
auto *DD = new (Context) DestructorDecl(Context.Id_deinit, CD->getLoc(),
selfDecl, CD);
auto *DD = new (Context) DestructorDecl(CD->getLoc(), selfDecl, CD);
DD->setImplicit();
-3
View File
@@ -840,9 +840,6 @@ struct MemberLookupResult {
/// The member is inaccessible (e.g. a private member in another file).
UR_Inaccessible,
// A type's destructor cannot be referenced
UR_DestructorInaccessible,
};
/// This is a list of considered, but rejected, candidates, along with a
+1 -3
View File
@@ -4969,12 +4969,10 @@ static void recordConformanceDependency(DeclContext *DC,
Conformance->getDeclContext()->getParentModule())
return;
auto &Context = DC->getASTContext();
// FIXME: 'deinit' is being used as a dummy identifier here. Really we
// don't care about /any/ of the type's members, only that it conforms to
// the protocol.
tracker->addUsedMember({Adoptee, Context.Id_deinit},
tracker->addUsedMember({Adoptee, DeclBaseName::createDestructor()},
DC->isCascadingContextForLookup(InExpression));
}
+4 -2
View File
@@ -1623,6 +1623,8 @@ DeclBaseName ModuleFile::getDeclBaseName(IdentifierID IID) {
llvm_unreachable("Cannot get DeclBaseName of special module id");
case SUBSCRIPT_ID:
return DeclBaseName::createSubscript();
case serialization::DESTRUCTOR_ID:
return DeclBaseName::createDestructor();
case NUM_SPECIAL_IDS:
llvm_unreachable("implementation detail only");
}
@@ -1805,6 +1807,7 @@ ModuleDecl *ModuleFile::getModule(ModuleID MID) {
return clangImporter->getImportedHeaderModule();
}
case SUBSCRIPT_ID:
case DESTRUCTOR_ID:
llvm_unreachable("Modules cannot be named with special names");
case NUM_SPECIAL_IDS:
llvm_unreachable("implementation detail only");
@@ -3550,8 +3553,7 @@ ModuleFile::getDeclChecked(DeclID DID, Optional<DeclContext *> ForcedContext) {
if (declOrOffset.isComplete())
return declOrOffset;
auto dtor = createDecl<DestructorDecl>(ctx.Id_deinit, SourceLoc(),
/*selfpat*/nullptr, DC);
auto dtor = createDecl<DestructorDecl>(SourceLoc(), /*selfpat*/nullptr, DC);
declOrOffset = dtor;
configureGenericEnvironment(dtor, genericEnvID);
+2
View File
@@ -341,6 +341,8 @@ public:
}
case static_cast<uint8_t>(DeclNameKind::Subscript):
return {DeclBaseName::Kind::Subscript, StringRef()};
case static_cast<uint8_t>(DeclNameKind::Destructor):
return {DeclBaseName::Kind::Destructor, StringRef()};
default:
llvm_unreachable("Unknown DeclNameKind");
}
+8 -1
View File
@@ -91,6 +91,8 @@ namespace {
return llvm::HashString(key.getIdentifier().str());
case DeclBaseName::Kind::Subscript:
return static_cast<uint8_t>(DeclNameKind::Subscript);
case DeclBaseName::Kind::Destructor:
return static_cast<uint8_t>(DeclNameKind::Destructor);
}
}
@@ -119,6 +121,9 @@ namespace {
case DeclBaseName::Kind::Subscript:
writer.write<uint8_t>(static_cast<uint8_t>(DeclNameKind::Subscript));
break;
case DeclBaseName::Kind::Destructor:
writer.write<uint8_t>(static_cast<uint8_t>(DeclNameKind::Destructor));
break;
}
}
@@ -509,6 +514,8 @@ IdentifierID Serializer::addDeclBaseNameRef(DeclBaseName ident) {
}
case DeclBaseName::Kind::Subscript:
return SUBSCRIPT_ID;
case DeclBaseName::Kind::Destructor:
return DESTRUCTOR_ID;
}
}
@@ -1784,7 +1791,7 @@ void Serializer::writeCrossReference(const DeclContext *DC, uint32_t pathLen) {
bool isProtocolExt = fn->getDeclContext()->getAsProtocolExtensionContext();
XRefValuePathPieceLayout::emitRecord(Out, ScratchRecord, abbrCode,
addTypeRef(ty),
addDeclBaseNameRef(fn->getName()),
addDeclBaseNameRef(fn->getBaseName()),
isProtocolExt,
fn->isStatic());
+1 -1
View File
@@ -443,7 +443,7 @@ class LazyProperties {
// CHECK-SEARCHES-NEXT: DefaultArgument {{.*}} [166:32 - 166:32] expanded
// CHECK-SEARCHES-NEXT: Module name=scope_map
// CHECK-SEARCHES-NEXT: FileUnit file="{{.*}}scope_map.swift"
// CHECK-SEARCHES-NEXT: AbstractFunctionDecl name=defaultArguments : (Int, Int) -> ()
// CHECK-SEARCHES-NEXT: AbstractFunctionDecl name=defaultArguments(i:j:) : (Int, Int) -> ()
// CHECK-SEARCHES-NEXT: {{.*}} Initializer DefaultArgument index=0
// CHECK-SEARCHES-LABEL: ***Scope at 179:18***
+9
View File
@@ -183,3 +183,12 @@ class SubscriptAsFunction {
// CHECK-LABEL: sil_vtable SubscriptAsFunction {
// CHECK-NOT: #SubscriptAsFunction.subscript
// CHECK: #SubscriptAsFunction.`subscript`!1
class DeinitAsFunction {
func `deinit`() {}
}
// CHECK-LABEL: sil_vtable DeinitAsFunction {
// CHECK: #DeinitAsFunction.`deinit`!1
// CHECK: #DeinitAsFunction.deinit!deallocator
@@ -3,7 +3,6 @@
// A class with no initializers (which has non-initialized properties so a
// default constructor can be synthesized) should produce an error.
class NoInitializers { // expected-error {{class 'NoInitializers' has no initializers}}
// expected-note@-1 {{did you mean 'deinit'?}}
var x: Double // expected-note {{stored property 'x' without initial value prevents synthesized initializers}}
func foo() {
+23
View File
@@ -54,3 +54,26 @@ let sr3043 = SR3043Derived()
sr3043.deinit() // expected-error {{deinitializers cannot be accessed}}
sr3043.deinit // expected-error {{deinitializers cannot be accessed}}
SR3043Derived.deinit() // expected-error {{deinitializers cannot be accessed}}
// Allow deinit functions in classes
class ClassWithDeinitFunc {
func `deinit`() {
}
func `deinit`(a: SR3043Base) {
}
}
let instanceWithDeinitFunc = ClassWithDeinitFunc()
instanceWithDeinitFunc.deinit()
_ = instanceWithDeinitFunc.deinit(a:)
_ = instanceWithDeinitFunc.deinit as () -> Void
SR3043Derived.deinit() // expected-error {{deinitializers cannot be accessed}}
class ClassWithDeinitMember {
var `deinit`: SR3043Base?
}
let instanceWithDeinitMember = ClassWithDeinitMember()
_ = instanceWithDeinitMember.deinit