mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Hash the basename of a source file to use as a discriminator for 'private'.
Now we can test the mangling rules set up in the previous commit: include the discriminator for the top-most 'private' decl, but not anything nested within it. Part of rdar://problem/17632175 Swift SVN r21599
This commit is contained in:
@@ -522,8 +522,8 @@ public:
|
||||
/// which distinguishes \p D from other declarations in the same module with
|
||||
/// the same name.
|
||||
///
|
||||
/// Since this value is used in name mangling, it should contain only
|
||||
/// ASCII identifier characters.
|
||||
/// Since this value is used in name mangling, it should be a valid ASCII-only
|
||||
/// identifier.
|
||||
virtual void getDiscriminatorForPrivateValue(SmallVectorImpl<char> &buffer,
|
||||
const ValueDecl *D) const = 0;
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include "swift/AST/Module.h"
|
||||
#include "swift/AST/ProtocolConformance.h"
|
||||
#include "swift/Basic/Punycode.h"
|
||||
#include "clang/Basic/CharInfo.h"
|
||||
#include "clang/AST/Decl.h"
|
||||
#include "clang/AST/DeclObjC.h"
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
@@ -447,13 +448,16 @@ void Mangler::mangleDeclName(ValueDecl *decl) {
|
||||
auto topLevelContext = decl->getDeclContext()->getModuleScopeContext();
|
||||
auto fileUnit = cast<FileUnit>(topLevelContext);
|
||||
|
||||
SmallString<32> discriminator;
|
||||
SmallString<64> discriminator;
|
||||
fileUnit->getDiscriminatorForPrivateValue(discriminator, decl);
|
||||
assert(!discriminator.empty());
|
||||
assert(!isNonAscii(discriminator) &&
|
||||
"discriminator contains non-ASCII characters");
|
||||
assert(!clang::isDigit(discriminator.front()) &&
|
||||
"not a valid identifier");
|
||||
|
||||
// Manually construct an <identifier> mangling here.
|
||||
Buffer << 'P' << (discriminator.size()+1) << '_' << discriminator.str();
|
||||
Buffer << 'P' << discriminator.size() << discriminator.str();
|
||||
}
|
||||
// Fall through to mangle the name.
|
||||
}
|
||||
|
||||
@@ -31,7 +31,10 @@
|
||||
#include "llvm/ADT/DenseSet.h"
|
||||
#include "llvm/ADT/TinyPtrVector.h"
|
||||
#include "llvm/ADT/SmallPtrSet.h"
|
||||
#include "llvm/ADT/StringExtras.h"
|
||||
#include "llvm/Support/MD5.h"
|
||||
#include "llvm/Support/MemoryBuffer.h"
|
||||
#include "llvm/Support/Path.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include "llvm/Support/SaveAndRestore.h"
|
||||
|
||||
@@ -1378,9 +1381,42 @@ void
|
||||
SourceFile::getDiscriminatorForPrivateValue(SmallVectorImpl<char> &buffer,
|
||||
const ValueDecl *D) const {
|
||||
assert(D->getDeclContext()->getModuleScopeContext() == this);
|
||||
// FIXME: Actually come up with a discriminator.
|
||||
StringRef discriminator = getParentModule()->Name.str();
|
||||
buffer.append(discriminator.begin(), discriminator.end());
|
||||
|
||||
StringRef name = getFilename();
|
||||
if (name.empty()) {
|
||||
assert(1 == std::count_if(getParentModule()->getFiles().begin(),
|
||||
getParentModule()->getFiles().end(),
|
||||
[](const FileUnit *FU) -> bool {
|
||||
return isa<SourceFile>(FU) && cast<SourceFile>(FU)->getFilename().empty();
|
||||
}) && "can't promise uniqueness if multiple source files are nameless");
|
||||
|
||||
// We still need a discriminator.
|
||||
buffer.push_back('_');
|
||||
return;
|
||||
}
|
||||
|
||||
// Use a hash of the basename of the source file as our discriminator.
|
||||
// This keeps us from leaking information about the original filename
|
||||
// while still providing uniqueness. Using the basename makes the
|
||||
// discriminator invariant across source checkout locations.
|
||||
// FIXME: Use a faster hash here? We don't need security, just uniqueness.
|
||||
llvm::MD5 hash;
|
||||
hash.update(llvm::sys::path::filename(name));
|
||||
llvm::MD5::MD5Result result;
|
||||
hash.final(result);
|
||||
|
||||
// Make sure the whole thing is a valid identifier.
|
||||
buffer.push_back('_');
|
||||
|
||||
// Write the hash as a hex string.
|
||||
// FIXME: This should go into llvm/ADT/StringExtras.h.
|
||||
// FIXME: And there are more compact ways to encode a 16-byte value.
|
||||
buffer.reserve(buffer.size() + 2*llvm::array_lengthof(result));
|
||||
for (uint8_t byte : result) {
|
||||
buffer.push_back(llvm::hexdigit(byte >> 4, /*lowercase=*/false));
|
||||
buffer.push_back(llvm::hexdigit(byte & 0xF, /*lowercase=*/false));
|
||||
}
|
||||
// FIXME: Cache the result?
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
51
test/SILGen/mangling_private.swift
Normal file
51
test/SILGen/mangling_private.swift
Normal file
@@ -0,0 +1,51 @@
|
||||
// RUN: rm -rf %t && mkdir %t
|
||||
// RUN: %swift %s -emit-silgen | FileCheck %s
|
||||
|
||||
// RUN: cp %s %t
|
||||
// RUN: %swift %t/mangling_private.swift -emit-silgen | FileCheck %s
|
||||
|
||||
// RUN: cp %s %t/other_name.swift
|
||||
// RUN: %swift %t/other_name.swift -emit-silgen -module-name mangling_private | FileCheck %s -check-prefix=OTHER-NAME
|
||||
|
||||
// CHECK-LABEL: sil @_TF16mangling_privateP33_713AFCDB29B710C2AB6F4DF7C1C8FEC911privateFuncFT_Si
|
||||
// OTHER-NAME-LABEL: sil @_TF16mangling_privateP33_AD9C6D430861F1E1D66B54DBCA7CC94B11privateFuncFT_Si
|
||||
private func privateFunc() -> Int {
|
||||
return 0
|
||||
}
|
||||
|
||||
public struct PublicStruct {
|
||||
// CHECK-LABEL: sil @_TFV16mangling_private12PublicStructP33_713AFCDB29B710C2AB6F4DF7C1C8FEC913privateMethodfMS0_FT_T_
|
||||
private static func privateMethod() {}
|
||||
}
|
||||
|
||||
public struct InternalStruct {
|
||||
// CHECK-LABEL: sil @_TFV16mangling_private14InternalStructP33_713AFCDB29B710C2AB6F4DF7C1C8FEC913privateMethodfMS0_FT_T_
|
||||
private static func privateMethod() {}
|
||||
}
|
||||
|
||||
private struct PrivateStruct {
|
||||
// CHECK-LABEL: sil @_TFV16mangling_privateP33_713AFCDB29B710C2AB6F4DF7C1C8FEC913PrivateStruct13privateMethodfMS0_FT_T_
|
||||
private static func privateMethod() {}
|
||||
|
||||
struct Inner {
|
||||
// CHECK-LABEL: sil @_TFVV16mangling_privateP33_713AFCDB29B710C2AB6F4DF7C1C8FEC913PrivateStruct5Inner13privateMethodfMS1_FT_T_
|
||||
private static func privateMethod() {}
|
||||
}
|
||||
}
|
||||
|
||||
func localTypes() {
|
||||
struct LocalStruct {
|
||||
// CHECK-LABEL: sil shared @_TFVF16mangling_private10localTypesFT_T_L_11LocalStruct13privateMethodfMS0_FT_T_
|
||||
private static func privateMethod() {}
|
||||
}
|
||||
}
|
||||
|
||||
extension PublicStruct {
|
||||
// CHECK-LABEL: sil @_TFV16mangling_private12PublicStructP33_713AFCDB29B710C2AB6F4DF7C1C8FEC916extPrivateMethodfS0_FT_T_
|
||||
private func extPrivateMethod() {}
|
||||
}
|
||||
extension PrivateStruct {
|
||||
// CHECK-LABEL: sil @_TFV16mangling_privateP33_713AFCDB29B710C2AB6F4DF7C1C8FEC913PrivateStructP33_713AFCDB29B710C2AB6F4DF7C1C8FEC916extPrivateMethodfS0_FT_T_
|
||||
private func extPrivateMethod() {}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user