Skip to content

Introduce special decl names #9989

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jul 11, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 36 additions & 4 deletions include/swift/AST/Identifier.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ enum class DeclRefKind {
/// ASTContext. It just wraps a nul-terminated "const char*".
class Identifier {
friend class ASTContext;
friend class DeclBaseName;

const char *Pointer;

/// Constructor, only accessible by ASTContext, which handles the uniquing.
Expand Down Expand Up @@ -207,14 +209,39 @@ namespace swift {
/// Wrapper that may either be an Identifier or a special name
/// (e.g. for subscripts)
class DeclBaseName {
public:
enum class Kind: uint8_t {
Normal,
Subscript
};

private:
/// In a special DeclName represenenting a subscript, this opaque pointer
/// is used as the data of the base name identifier.
/// This is an implementation detail that should never leak outside of
/// DeclName.
static void *SubscriptIdentifierData;

Identifier Ident;

public:
DeclBaseName() : DeclBaseName(Identifier()) {}

DeclBaseName(Identifier I) : Ident(I) {}

bool isSpecial() const { return false; }
static DeclBaseName createSubscript() {
return DeclBaseName(Identifier((const char *)SubscriptIdentifierData));
}

Kind getKind() const {
if (Ident.get() == SubscriptIdentifierData) {
return Kind::Subscript;
} else {
return Kind::Normal;
}
}

bool isSpecial() const { return getKind() != Kind::Normal; }

/// Return the identifier backing the name. Assumes that the name is not
/// special.
Expand All @@ -238,12 +265,17 @@ class DeclBaseName {
StringRef userFacingName() const {
if (empty())
return "_";
return getIdentifier().str();

switch (getKind()) {
case Kind::Normal:
return getIdentifier().str();
case Kind::Subscript:
return "subscript";
}
}

int compare(DeclBaseName other) const {
// TODO: Sort special names cleverly
return getIdentifier().compare(other.getIdentifier());
return userFacingName().compare(other.userFacingName());
}

bool operator==(StringRef Str) const {
Expand Down
1 change: 0 additions & 1 deletion include/swift/AST/KnownIdentifiers.def
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,6 @@ IDENTIFIER(simd)
IDENTIFIER(some)
IDENTIFIER(storage)
IDENTIFIER(stringValue)
IDENTIFIER(subscript)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎉

IDENTIFIER(super)
IDENTIFIER(superDecoder)
IDENTIFIER(superEncoder)
Expand Down
6 changes: 5 additions & 1 deletion include/swift/Serialization/ModuleFile.h
Original file line number Diff line number Diff line change
Expand Up @@ -740,7 +740,11 @@ class ModuleFile : public LazyMemberLoader {
/// Returns the type with the given ID, deserializing it if needed.
llvm::Expected<Type> getTypeChecked(serialization::TypeID TID);

/// Returns the identifier with the given ID, deserializing it if needed.
/// Returns the base name with the given ID, deserializing it if needed.
DeclBaseName getDeclBaseName(serialization::IdentifierID IID);

/// Convenience method to retrieve the identifier backing the name with
/// given ID. Asserts that the name with this ID is not special.
Identifier getIdentifier(serialization::IdentifierID IID);

/// Returns the decl with the given ID, deserializing it if needed.
Expand Down
17 changes: 13 additions & 4 deletions include/swift/Serialization/ModuleFormat.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 = 349; // Last change: '@autoclosure' and '@noescape' no longer decl attributes.
const uint16_t VERSION_MINOR = 350; // Last change: special decl names

using DeclID = PointerEmbeddedInt<unsigned, 31>;
using DeclIDField = BCFixed<31>;
Expand Down Expand Up @@ -342,18 +342,27 @@ using OptionalTypeKindField = BCFixed<2>;

// These IDs must \em not be renumbered or reordered without incrementing
// VERSION_MAJOR.
enum SpecialModuleID : uint8_t {
enum class DeclNameKind: uint8_t {
Normal,
Subscript
};

// These IDs must \em not be renumbered or reordered without incrementing
// VERSION_MAJOR.
enum SpecialIdentifierID : uint8_t {
/// Special IdentifierID value for the Builtin module.
BUILTIN_MODULE_ID = 0,
/// Special IdentifierID value for the current module.
CURRENT_MODULE_ID,
/// Special value for the module for imported Objective-C headers.
OBJC_HEADER_MODULE_ID,
/// Special value for the special subscript name
SUBSCRIPT_ID,

/// The number of special modules. This value should never be encoded;
/// 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
/// is correct and necessary to add new values above this one.
NUM_SPECIAL_MODULES
NUM_SPECIAL_IDS
};

// These IDs must \em not be renumbered or reordered without incrementing
Expand Down
11 changes: 9 additions & 2 deletions lib/AST/ASTMangler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -540,8 +540,15 @@ void ASTMangler::appendDeclName(const ValueDecl *decl) {
break;
}
} else if (decl->hasName()) {
// TODO: Handle special names
appendIdentifier(decl->getBaseName().getIdentifier().str());
// FIXME: Should a mangled subscript name contain the string "subscript"?
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Something @eeckstein may have an opinion on, but can be changed in a follow-up commit.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wanted to start a thread about that once the changes have been landed

switch (decl->getBaseName().getKind()) {
case DeclBaseName::Kind::Normal:
appendIdentifier(decl->getBaseName().getIdentifier().str());
break;
case DeclBaseName::Kind::Subscript:
appendIdentifier("subscript");
break;
}
} else {
assert(AllowNamelessEntities && "attempt to mangle unnamed decl");
// Fall back to an unlikely name, so that we still generate a valid
Expand Down
2 changes: 2 additions & 0 deletions lib/AST/Identifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
#include "llvm/Support/ConvertUTF.h"
using namespace swift;

void *DeclBaseName::SubscriptIdentifierData =
&DeclBaseName::SubscriptIdentifierData;

raw_ostream &llvm::operator<<(raw_ostream &OS, Identifier I) {
if (I.get() == nullptr)
Expand Down
9 changes: 4 additions & 5 deletions lib/ClangImporter/ClangImporter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2974,7 +2974,7 @@ void ClangImporter::Implementation::lookupValue(
auto &clangCtx = getClangASTContext();
auto clangTU = clangCtx.getTranslationUnitDecl();

for (auto entry : table.lookup(name.getBaseIdentifier().str(), clangTU)) {
for (auto entry : table.lookup(name.getBaseName(), clangTU)) {
// If the entry is not visible, skip it.
if (!isVisibleClangEntry(clangCtx, entry)) continue;

Expand Down Expand Up @@ -3070,7 +3070,7 @@ void ClangImporter::Implementation::lookupVisibleDecls(

// Look for namespace-scope entities with each base name.
for (auto baseName : baseNames) {
lookupValue(table, SwiftContext.getIdentifier(baseName), consumer);
lookupValue(table, baseName.toDeclBaseName(SwiftContext), consumer);
}
}

Expand All @@ -3079,9 +3079,8 @@ void ClangImporter::Implementation::lookupObjCMembers(
DeclName name,
VisibleDeclConsumer &consumer) {
auto &clangCtx = getClangASTContext();
auto baseName = name.getBaseIdentifier().str();

for (auto clangDecl : table.lookupObjCMembers(baseName)) {
for (auto clangDecl : table.lookupObjCMembers(name.getBaseName())) {
// If the entry is not visible, skip it.
if (!isVisibleClangEntry(clangCtx, clangDecl)) continue;

Expand Down Expand Up @@ -3121,7 +3120,7 @@ void ClangImporter::Implementation::lookupAllObjCMembers(

// Look for Objective-C members with each base name.
for (auto baseName : baseNames) {
lookupObjCMembers(table, SwiftContext.getIdentifier(baseName), consumer);
lookupObjCMembers(table, baseName.toDeclBaseName(SwiftContext), consumer);
}
}

Expand Down
4 changes: 2 additions & 2 deletions lib/ClangImporter/ImportDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5410,7 +5410,7 @@ SwiftDeclConverter::getImplicitProperty(ImportedName importedName,
Impl.findLookupTable(*getClangSubmoduleForDecl(accessor));
assert(lookupTable && "No lookup table?");
bool foundAccessor = false;
for (auto entry : lookupTable->lookup(propertyName.str(),
for (auto entry : lookupTable->lookup(SerializedSwiftName(propertyName),
importedName.getEffectiveContext())) {
auto decl = entry.dyn_cast<clang::NamedDecl *>();
if (!decl)
Expand Down Expand Up @@ -6246,7 +6246,7 @@ SwiftDeclConverter::importSubscript(Decl *decl,
// Build the subscript declaration.
auto &C = Impl.SwiftContext;
auto bodyParams = getterThunk->getParameterList(1)->clone(C);
DeclName name(C, C.Id_subscript, {Identifier()});
DeclName name(C, DeclBaseName::createSubscript(), {Identifier()});
auto subscript = Impl.createDeclWithClangNode<SubscriptDecl>(
getter->getClangNode(), getOverridableAccessibility(dc), name,
decl->getLoc(), bodyParams, decl->getLoc(),
Expand Down
Loading