Skip to content

Commit b9c2a69

Browse files
committed
Introduce special decl names
Special DeclNames represent names that do not have an identifier in the surface language. This implies serializing the information about whether a name is special together with its identifier (if it is not special) in both the module file and the swift lookup table. ValueDecls are not guaranteed to have a name anymore and thus getNameStr is moved from ValueDecl to subclasses that guarantee to be backed by identifiers. Other calls need to handle special names if the context doesn't guarantee that the declaration's name is non-special.
1 parent e9b2c13 commit b9c2a69

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+522
-203
lines changed

include/swift/AST/Decl.h

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2104,13 +2104,6 @@ class ValueDecl : public Decl {
21042104
bool hasName() const { return bool(Name); }
21052105
bool isOperator() const { return Name.isOperator(); }
21062106

2107-
/// Returns the string for the base name, or "_" if this is unnamed.
2108-
StringRef getNameStr() const {
2109-
// TODO: Check if this function is called for special names
2110-
assert(!Name.isSpecial() && "Cannot get string for special names");
2111-
return hasName() ? Name.getBaseName().getIdentifier().str() : "_";
2112-
}
2113-
21142107
/// Retrieve the full name of the declaration.
21152108
/// TODO: Rename to getName?
21162109
DeclName getFullName() const { return Name; }
@@ -2329,6 +2322,12 @@ class TypeDecl : public ValueDecl {
23292322
public:
23302323
Identifier getName() const { return getFullName().getBaseIdentifier(); }
23312324

2325+
/// Returns the string for the base name, or "_" if this is unnamed.
2326+
StringRef getNameStr() const {
2327+
assert(!getFullName().isSpecial() && "Cannot get string for special names");
2328+
return hasName() ? getBaseName().getIdentifier().str() : "_";
2329+
}
2330+
23322331
/// The type of this declaration's values. For the type of the
23332332
/// declaration itself, use getInterfaceType(), which returns a
23342333
/// metatype.
@@ -4215,6 +4214,12 @@ class VarDecl : public AbstractStorageDecl {
42154214

42164215
Identifier getName() const { return getFullName().getBaseIdentifier(); }
42174216

4217+
/// Returns the string for the base name, or "_" if this is unnamed.
4218+
StringRef getNameStr() const {
4219+
assert(!getFullName().isSpecial() && "Cannot get string for special names");
4220+
return hasName() ? getBaseName().getIdentifier().str() : "_";
4221+
}
4222+
42184223
TypeLoc &getTypeLoc() { return typeLoc; }
42194224
TypeLoc getTypeLoc() const { return typeLoc; }
42204225

@@ -4684,6 +4689,12 @@ class AbstractFunctionDecl : public ValueDecl, public GenericContext {
46844689
public:
46854690
Identifier getName() const { return getFullName().getBaseIdentifier(); }
46864691

4692+
/// Returns the string for the base name, or "_" if this is unnamed.
4693+
StringRef getNameStr() const {
4694+
assert(!getFullName().isSpecial() && "Cannot get string for special names");
4695+
return hasName() ? getBaseName().getIdentifier().str() : "_";
4696+
}
4697+
46874698
/// \brief Should this declaration be treated as if annotated with transparent
46884699
/// attribute.
46894700
bool isTransparent() const;
@@ -5307,6 +5318,12 @@ class EnumElementDecl : public ValueDecl {
53075318

53085319
Identifier getName() const { return getFullName().getBaseIdentifier(); }
53095320

5321+
/// Returns the string for the base name, or "_" if this is unnamed.
5322+
StringRef getNameStr() const {
5323+
assert(!getFullName().isSpecial() && "Cannot get string for special names");
5324+
return hasName() ? getBaseName().getIdentifier().str() : "_";
5325+
}
5326+
53105327
/// \returns false if there was an error during the computation rendering the
53115328
/// EnumElementDecl invalid, true otherwise.
53125329
bool computeType();

include/swift/AST/Identifier.h

Lines changed: 45 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ enum class DeclRefKind {
5151
/// ASTContext. It just wraps a nul-terminated "const char*".
5252
class Identifier {
5353
friend class ASTContext;
54+
friend class DeclBaseName;
55+
5456
const char *Pointer;
5557

5658
/// Constructor, only accessible by ASTContext, which handles the uniquing.
@@ -206,15 +208,45 @@ namespace swift {
206208

207209
/// Wrapper that may either be an Identifier or a special name
208210
/// (e.g. for subscripts)
211+
///
212+
/// The raw values of this enum are used in serialization by both
213+
/// BaseNameToEntitiesTable(Reader|Writer)Info and DeclTableInfo. For every
214+
/// reordering, deletion or insertion of any case, the major (resp. minor)
215+
/// version of both SwiftLookupTable AND ModuleFormat must thus be incremented.
209216
class DeclBaseName {
217+
public:
218+
enum class Kind : uint8_t {
219+
Normal = 0,
220+
Subscript
221+
};
222+
223+
private:
224+
/// In a special DeclName represenenting a subscript, this opaque pointer
225+
/// is used as the data of the base name identifier.
226+
/// This is an implementation detail that should never leak outside of
227+
/// DeclName.
228+
static void *SubscriptIdentifierData;
229+
210230
Identifier Ident;
211231

212232
public:
213233
DeclBaseName() : DeclBaseName(Identifier()) {}
214234

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

217-
bool isSpecial() const { return false; }
237+
static DeclBaseName createSubscript() {
238+
return DeclBaseName(Identifier((const char *)SubscriptIdentifierData));
239+
}
240+
241+
Kind getKind() const {
242+
if (Ident.get() == SubscriptIdentifierData) {
243+
return Kind::Subscript;
244+
} else {
245+
return Kind::Normal;
246+
}
247+
}
248+
249+
bool isSpecial() const { return getKind() != Kind::Normal; }
218250

219251
/// Return the identifier backing the name. Assumes that the name is not
220252
/// special.
@@ -233,9 +265,19 @@ class DeclBaseName {
233265
return !isSpecial() && getIdentifier().isEditorPlaceholder();
234266
}
235267

268+
/// A representation of the name to be displayed to users. May be ambiguous
269+
/// between identifiers and special names
270+
StringRef userFacingStr() const {
271+
switch (getKind()) {
272+
case Kind::Normal:
273+
return getIdentifier().str();
274+
case Kind::Subscript:
275+
return "subscript";
276+
}
277+
}
278+
236279
int compare(DeclBaseName other) const {
237-
// TODO: Sort special names cleverly
238-
return getIdentifier().compare(other.getIdentifier());
280+
return userFacingStr().compare(other.userFacingStr());
239281
}
240282

241283
bool operator==(StringRef Str) const {
@@ -253,7 +295,6 @@ class DeclBaseName {
253295
const void *getAsOpaquePointer() const { return Ident.get(); }
254296

255297
static DeclBaseName getFromOpaquePointer(void *P) {
256-
// TODO: Check if P is a special name
257298
return Identifier::getFromOpaquePointer(P);
258299
}
259300

@@ -387,7 +428,6 @@ class DeclName {
387428
auto baseName = getBaseName();
388429
assert(!baseName.isSpecial() &&
389430
"Can't retrieve the identifier of a special base name");
390-
// FIXME: Do we need this method?
391431
return baseName.getIdentifier();
392432
}
393433

include/swift/Serialization/ModuleFile.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -737,7 +737,11 @@ class ModuleFile : public LazyMemberLoader {
737737
/// Returns the type with the given ID, deserializing it if needed.
738738
Type getType(serialization::TypeID TID);
739739

740-
/// Returns the identifier with the given ID, deserializing it if needed.
740+
/// Returns the base name with the given ID, deserializing it if needed.
741+
DeclBaseName getDeclBaseName(serialization::IdentifierID IID);
742+
743+
/// Convenience method to retrieve the identifier backing the name with
744+
/// given ID. Asserts that the name with this ID is not special.
741745
Identifier getIdentifier(serialization::IdentifierID IID);
742746

743747
/// Returns the decl with the given ID, deserializing it if needed.

include/swift/Serialization/ModuleFormat.h

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ const uint16_t VERSION_MAJOR = 0;
5454
/// in source control, you should also update the comment to briefly
5555
/// describe what change you made. The content of this comment isn't important;
5656
/// it just ensures a conflict if two people change the module format.
57-
const uint16_t VERSION_MINOR = 325; // Last change: unchecked_ownership_conver
57+
const uint16_t VERSION_MINOR = 326; // Last change: special decl names
5858

5959
using DeclID = PointerEmbeddedInt<unsigned, 31>;
6060
using DeclIDField = BCFixed<31>;
@@ -344,6 +344,18 @@ enum SpecialModuleID : uint8_t {
344344
NUM_SPECIAL_MODULES
345345
};
346346

347+
// Continuation of the special module IDs above for special names that don't
348+
// have an identifier. As above, these IDs must \em not be renumbered or
349+
// reordered without incrementing VERSION_MAJOR.
350+
enum SpecialNameID : uint8_t {
351+
SUBSCRIPT_ID = NUM_SPECIAL_MODULES,
352+
353+
/// The number of special modules and IDs. This value should never be encoded;
354+
/// it should only be used to count the number of names above. As such, it
355+
/// is correct and necessary to add new values above this one.
356+
NUM_SPECIAL_IDS
357+
};
358+
347359
// These IDs must \em not be renumbered or reordered without incrementing
348360
// VERSION_MAJOR.
349361
enum class EnumElementRawValueKind : uint8_t {

lib/AST/ASTMangler.cpp

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -391,8 +391,15 @@ void ASTMangler::appendDeclName(const ValueDecl *decl) {
391391
break;
392392
}
393393
} else {
394-
// TODO: Handle special names
395-
appendIdentifier(decl->getBaseName().getIdentifier().str());
394+
// FIXME: Should a mangled subscript name contain the string "substring"?
395+
switch (decl->getBaseName().getKind()) {
396+
case DeclBaseName::Kind::Normal:
397+
appendIdentifier(decl->getBaseName().getIdentifier().str());
398+
break;
399+
case DeclBaseName::Kind::Subscript:
400+
appendIdentifier("subscript");
401+
break;
402+
}
396403
}
397404

398405
if (decl->getDeclContext()->isLocalContext()) {

lib/AST/ASTVerifier.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2933,7 +2933,8 @@ bool swift::shouldVerify(const Decl *D, const ASTContext &Context) {
29332933
return true;
29342934
}
29352935

2936-
size_t Hash = llvm::hash_value(VD->getNameStr());
2936+
size_t Hash =
2937+
llvm::DenseMapInfo<DeclBaseName>::getHashValue(VD->getBaseName());
29372938
return Hash % ProcessCount == ProcessId;
29382939
#else
29392940
return false;

lib/AST/Decl.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -449,7 +449,8 @@ bool Decl::isPrivateStdlibDecl(bool whitelistProtocols) const {
449449
return false;
450450

451451
// If the name has leading underscore then it's a private symbol.
452-
if (VD->getNameStr().startswith("_"))
452+
if (!VD->getBaseName().isSpecial() &&
453+
VD->getBaseName().getIdentifier().str().startswith("_"))
453454
return true;
454455

455456
return false;

lib/AST/DiagnosticEngine.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -700,7 +700,7 @@ void DiagnosticEngine::emitDiagnostic(const Diagnostic &diagnostic) {
700700
}
701701

702702
if (auto value = dyn_cast<ValueDecl>(ppDecl)) {
703-
bufferName += value->getNameStr();
703+
bufferName += value->getBaseName().userFacingStr();
704704
} else if (auto ext = dyn_cast<ExtensionDecl>(ppDecl)) {
705705
bufferName += ext->getExtendedType().getString();
706706
}

lib/AST/Identifier.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
#include "llvm/Support/ConvertUTF.h"
2121
using namespace swift;
2222

23+
void *DeclBaseName::SubscriptIdentifierData =
24+
&DeclBaseName::SubscriptIdentifierData;
2325

2426
raw_ostream &llvm::operator<<(raw_ostream &OS, Identifier I) {
2527
if (I.get() == nullptr)
@@ -28,8 +30,9 @@ raw_ostream &llvm::operator<<(raw_ostream &OS, Identifier I) {
2830
}
2931

3032
raw_ostream &llvm::operator<<(raw_ostream &OS, DeclBaseName I) {
31-
// TODO: Handle special names
32-
return OS << I.getIdentifier();
33+
if (I.empty())
34+
return OS << "_";
35+
return OS << I.userFacingStr();
3336
}
3437

3538
raw_ostream &llvm::operator<<(raw_ostream &OS, DeclName I) {

lib/AST/Mangle.cpp

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -105,9 +105,17 @@ void Mangler::mangleIdentifier(Identifier ident, OperatorFixity fixity) {
105105

106106
/// Mangle an identifier into the buffer.
107107
void Mangler::mangleIdentifier(DeclBaseName ident, OperatorFixity fixity) {
108-
// TODO: Handle special names
109-
StringRef str = ident.getIdentifier().str();
110-
assert(!str.empty() && "mangling an empty identifier!");
108+
StringRef str;
109+
// FIXME: Should a serialized subscript name contain the string "substring"?
110+
switch (ident.getKind()) {
111+
case DeclBaseName::Kind::Normal:
112+
str = ident.getIdentifier().str();
113+
break;
114+
case DeclBaseName::Kind::Subscript:
115+
str = "subscript";
116+
break;
117+
}
118+
assert(!str.empty() && "mangling an empty name!");
111119
return mangleIdentifier(str, fixity, ident.isOperator());
112120
}
113121

lib/AST/NameLookup.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -138,9 +138,9 @@ bool swift::removeShadowedDecls(SmallVectorImpl<ValueDecl*> &decls,
138138
const ModuleDecl *curModule,
139139
LazyResolver *typeResolver) {
140140
// Category declarations by their signatures.
141-
llvm::SmallDenseMap<std::pair<CanType, Identifier>,
141+
llvm::SmallDenseMap<std::pair<CanType, DeclBaseName>,
142142
llvm::TinyPtrVector<ValueDecl *>>
143-
CollidingDeclGroups;
143+
CollidingDeclGroups;
144144

145145
/// Objective-C initializers are tracked by their context type and
146146
/// full name.
@@ -172,8 +172,8 @@ bool swift::removeShadowedDecls(SmallVectorImpl<ValueDecl*> &decls,
172172
signature = asd->getOverloadSignature().InterfaceType;
173173

174174
// If we've seen a declaration with this signature before, note it.
175-
auto &knownDecls = CollidingDeclGroups[std::make_pair(
176-
signature, decl->getBaseName().getIdentifier())];
175+
auto &knownDecls =
176+
CollidingDeclGroups[std::make_pair(signature, decl->getBaseName())];
177177
if (!knownDecls.empty())
178178
anyCollisions = true;
179179

lib/AST/SourceEntityWalker.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -93,9 +93,9 @@ bool SemaAnnotator::walkToDeclPre(Decl *D) {
9393
unsigned NameLen = 0;
9494

9595
if (ValueDecl *VD = dyn_cast<ValueDecl>(D)) {
96-
// TODO: Handle special names
97-
if (VD->hasName())
98-
NameLen = VD->getBaseName().getIdentifier().getLength();
96+
if (VD->hasName()) {
97+
NameLen = VD->getBaseName().userFacingStr().size();
98+
}
9999

100100
} else if (ExtensionDecl *ED = dyn_cast<ExtensionDecl>(D)) {
101101
SourceRange SR = ED->getExtendedTypeLoc().getSourceRange();

lib/AST/USRGeneration.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,8 @@ bool ide::printDeclUSR(const ValueDecl *D, raw_ostream &OS) {
195195
auto &Importer = *D->getASTContext().getClangModuleLoader();
196196

197197
auto ClangMacroInfo = ClangN.getAsMacro();
198-
bool Ignore = clang::index::generateUSRForMacro(D->getNameStr(),
198+
bool Ignore = clang::index::generateUSRForMacro(
199+
D->getBaseName().getIdentifier().str(),
199200
ClangMacroInfo->getDefinitionLoc(),
200201
Importer.getClangASTContext().getSourceManager(), Buf);
201202
if (!Ignore)

lib/ClangImporter/ClangImporter.cpp

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1802,7 +1802,9 @@ class DarwinBlacklistDeclConsumer : public swift::VisibleDeclConsumer {
18021802
return false;
18031803

18041804
if (clangModule->Name == "MacTypes") {
1805-
return llvm::StringSwitch<bool>(VD->getNameStr())
1805+
if (!VD->hasName() || VD->getBaseName().isSpecial())
1806+
return true;
1807+
return llvm::StringSwitch<bool>(VD->getBaseName().getIdentifier().str())
18061808
.Cases("OSErr", "OSStatus", "OptionBits", false)
18071809
.Cases("FourCharCode", "OSType", false)
18081810
.Case("Boolean", false)
@@ -2706,7 +2708,7 @@ void ClangImporter::Implementation::lookupValue(
27062708
auto &clangCtx = getClangASTContext();
27072709
auto clangTU = clangCtx.getTranslationUnitDecl();
27082710

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

@@ -2810,7 +2812,7 @@ void ClangImporter::Implementation::lookupVisibleDecls(
28102812

28112813
// Look for namespace-scope entities with each base name.
28122814
for (auto baseName : baseNames) {
2813-
lookupValue(table, SwiftContext.getIdentifier(baseName), consumer);
2815+
lookupValue(table, baseName.toDeclBaseName(SwiftContext), consumer);
28142816
}
28152817
}
28162818

@@ -2819,9 +2821,8 @@ void ClangImporter::Implementation::lookupObjCMembers(
28192821
DeclName name,
28202822
VisibleDeclConsumer &consumer) {
28212823
auto &clangCtx = getClangASTContext();
2822-
auto baseName = name.getBaseIdentifier().str();
28232824

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

@@ -2868,7 +2869,7 @@ void ClangImporter::Implementation::lookupAllObjCMembers(
28682869

28692870
// Look for Objective-C members with each base name.
28702871
for (auto baseName : baseNames) {
2871-
lookupObjCMembers(table, SwiftContext.getIdentifier(baseName), consumer);
2872+
lookupObjCMembers(table, baseName.toDeclBaseName(SwiftContext), consumer);
28722873
}
28732874
}
28742875

0 commit comments

Comments
 (0)