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:
Jordan Rose
2014-08-30 00:17:21 +00:00
parent 47658c87eb
commit 77daee9036
4 changed files with 98 additions and 7 deletions

View File

@@ -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;

View File

@@ -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.
}

View File

@@ -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?
}
//===----------------------------------------------------------------------===//

View 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() {}
}