Skip to content

Fix a pair of leaks related to FileUnit destructors not being run #26816

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 4 commits into from
Aug 26, 2019
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
39 changes: 9 additions & 30 deletions include/swift/AST/Module.h
Original file line number Diff line number Diff line change
Expand Up @@ -644,7 +644,10 @@ static inline unsigned alignOfFileUnit();
/// FileUnit is an abstract base class; its subclasses represent different
/// sorts of containers that can each provide a set of decls, e.g. a source
/// file. A module can contain several file-units.
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wnon-virtual-dtor"
class FileUnit : public DeclContext {
#pragma clang diagnostic pop
virtual void anchor();

// FIXME: Stick this in a PointerIntPair.
Expand All @@ -655,8 +658,6 @@ class FileUnit : public DeclContext {
: DeclContext(DeclContextKind::FileUnit, &M), Kind(kind) {
}

virtual ~FileUnit() = default;

public:
FileUnitKind getKind() const {
return Kind;
Expand Down Expand Up @@ -872,10 +873,6 @@ class FileUnit : public DeclContext {
return getParentModule()->getName().str();
}

/// If this is a module imported from a parseable interface, return the path
/// to the interface file, otherwise an empty StringRef.
virtual StringRef getParseableInterface() const { return {}; }

/// Traverse the decls within this file.
///
/// \returns true if traversal was aborted, false if it completed
Expand All @@ -895,13 +892,7 @@ class FileUnit : public DeclContext {
// Make placement new and vanilla new/delete illegal for FileUnits.
void *operator new(size_t Bytes) throw() = delete;
void *operator new(size_t Bytes, void *Mem) throw() = delete;

protected:
// Unfortunately we can't remove this altogether because the virtual
// destructor requires it to be accessible.
void operator delete(void *Data) throw() {
llvm_unreachable("Don't use operator delete on a SourceFile");
}
void operator delete(void *Data) throw() = delete;

public:
// Only allow allocation of FileUnits using the allocator in ASTContext
Expand Down Expand Up @@ -1384,35 +1375,23 @@ class BuiltinUnit final : public FileUnit {
};

/// Represents an externally-loaded file of some kind.
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wnon-virtual-dtor"
class LoadedFile : public FileUnit {
#pragma clang diagnostic pop
protected:
~LoadedFile() = default;
LoadedFile(FileUnitKind Kind, ModuleDecl &M) noexcept
: FileUnit(Kind, M) {
assert(classof(this) && "invalid kind");
}

/// A map from private/fileprivate decls to the file they were defined in.
llvm::DenseMap<const ValueDecl *, Identifier> FilenameForPrivateDecls;

public:

/// Returns an arbitrary string representing the storage backing this file.
///
/// This is usually a filesystem path.
virtual StringRef getFilename() const;

void addFilenameForPrivateDecl(const ValueDecl *decl, Identifier id) {
assert(!FilenameForPrivateDecls.count(decl) ||
FilenameForPrivateDecls[decl] == id);
FilenameForPrivateDecls[decl] = id;
}

StringRef getFilenameForPrivateDecl(const ValueDecl *decl) {
auto it = FilenameForPrivateDecls.find(decl);
if (it == FilenameForPrivateDecls.end())
return StringRef();
return it->second.str();
virtual StringRef getFilenameForPrivateDecl(const ValueDecl *decl) const {
return StringRef();
}

/// Look up an operator declaration.
Expand Down
2 changes: 0 additions & 2 deletions include/swift/ClangImporter/ClangModule.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,6 @@ class ClangModuleUnit final : public LoadedFile {
/// The metadata of the underlying Clang module.
clang::ExternalASTSource::ASTSourceDescriptor ASTSourceDescriptor;

~ClangModuleUnit() = default;

public:
/// True if the given Module contains an imported Clang module unit.
static bool hasClangModule(ModuleDecl *M);
Expand Down
8 changes: 8 additions & 0 deletions include/swift/Serialization/ModuleFile.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,11 @@ class ModuleFile
/// The target the module was built for.
StringRef TargetTriple;

/// The name of the module interface this module was compiled from.
///
/// Empty if this module didn't come from an interface file.
StringRef ModuleInterfacePath;

/// The Swift compatibility version in use when this module was built.
version::Version CompatibilityVersion;

Expand Down Expand Up @@ -391,6 +396,7 @@ class ModuleFile
std::unique_ptr<SerializedObjCMethodTable> ObjCMethods;

llvm::DenseMap<const ValueDecl *, Identifier> PrivateDiscriminatorsByValue;
llvm::DenseMap<const ValueDecl *, StringRef> FilenamesForPrivateValues;

TinyPtrVector<Decl *> ImportDecls;

Expand Down Expand Up @@ -762,6 +768,8 @@ class ModuleFile
void getDisplayDecls(SmallVectorImpl<Decl*> &results);

StringRef getModuleFilename() const {
if (!ModuleInterfacePath.empty())
return ModuleInterfacePath;
// FIXME: This seems fragile, maybe store the filename separately ?
return ModuleInputBuffer->getBufferIdentifier();
}
Expand Down
16 changes: 3 additions & 13 deletions include/swift/Serialization/SerializedModuleLoader.h
Original file line number Diff line number Diff line change
Expand Up @@ -251,14 +251,8 @@ class SerializedASTFile final : public LoadedFile {

ModuleFile &File;

/// The parseable interface this module was generated from if any.
/// Used for debug info.
std::string ParseableInterface;

bool IsSIB;

~SerializedASTFile() = default;

SerializedASTFile(ModuleDecl &M, ModuleFile &file, bool isSIB = false)
: LoadedFile(FileUnitKind::SerializedAST, M), File(file), IsSIB(isSIB) {}

Expand All @@ -278,6 +272,9 @@ class SerializedASTFile final : public LoadedFile {
DeclName name, NLKind lookupKind,
SmallVectorImpl<ValueDecl*> &results) const override;

virtual StringRef
getFilenameForPrivateDecl(const ValueDecl *decl) const override;

virtual TypeDecl *lookupLocalType(StringRef MangledName) const override;

virtual OpaqueTypeDecl *
Expand Down Expand Up @@ -351,13 +348,6 @@ class SerializedASTFile final : public LoadedFile {

virtual const clang::Module *getUnderlyingClangModule() const override;

/// If this is a module imported from a parseable interface, return the path
/// to the interface file, otherwise an empty StringRef.
virtual StringRef getParseableInterface() const override {
return ParseableInterface;
}
void setParseableInterface(StringRef PI) { ParseableInterface = PI; }

virtual bool getAllGenericSignatures(
SmallVectorImpl<GenericSignature*> &genericSignatures)
override;
Expand Down
3 changes: 0 additions & 3 deletions include/swift/Serialization/Validation.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,6 @@ struct ValidationInfo {
class ExtendedValidationInfo {
SmallVector<StringRef, 4> ExtraClangImporterOpts;
StringRef SDKPath;
StringRef ParseableInterface;
struct {
unsigned ArePrivateImportsEnabled : 1;
unsigned IsSIB : 1;
Expand All @@ -114,8 +113,6 @@ class ExtendedValidationInfo {
void addExtraClangImporterOption(StringRef option) {
ExtraClangImporterOpts.push_back(option);
}
StringRef getParseableInterface() const { return ParseableInterface; }
void setParseableInterface(StringRef PI) { ParseableInterface = PI; }

bool isSIB() const { return Bits.IsSIB; }
void setIsSIB(bool val) {
Expand Down
9 changes: 5 additions & 4 deletions lib/AST/Module.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,11 @@

using namespace swift;

static_assert(IsTriviallyDestructible<FileUnit>::value,
"FileUnits are BumpPtrAllocated; the d'tor may not be called");
static_assert(IsTriviallyDestructible<LoadedFile>::value,
"LoadedFiles are BumpPtrAllocated; the d'tor may not be called");

//===----------------------------------------------------------------------===//
// Builtin Module Name lookup
//===----------------------------------------------------------------------===//
Expand Down Expand Up @@ -1249,10 +1254,6 @@ StringRef ModuleDecl::getModuleFilename() const {
// per-file names. Modules can consist of more than one file.
StringRef Result;
for (auto F : getFiles()) {
Result = F->getParseableInterface();
if (!Result.empty())
return Result;

if (auto SF = dyn_cast<SourceFile>(F)) {
if (!Result.empty())
return StringRef();
Expand Down
3 changes: 3 additions & 0 deletions lib/ClangImporter/ClangImporter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3176,6 +3176,9 @@ void ClangImporter::verifyAllModules() {
// ClangModule Implementation
//===----------------------------------------------------------------------===//

static_assert(IsTriviallyDestructible<ClangModuleUnit>::value,
"ClangModuleUnits are BumpPtrAllocated; the d'tor is not called");

ClangModuleUnit::ClangModuleUnit(ModuleDecl &M,
ClangImporter::Implementation &owner,
const clang::Module *clangModule)
Expand Down
4 changes: 3 additions & 1 deletion lib/ClangImporter/DWARFImporter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ void DWARFImporterDelegate::anchor() {}
/// Represents a Clang module that was "imported" from debug info. Since all the
/// loading of types is done on demand, this class is effectively empty.
class DWARFModuleUnit final : public LoadedFile {
~DWARFModuleUnit() = default;
ClangImporter::Implementation &Owner;

public:
Expand Down Expand Up @@ -96,6 +95,9 @@ class DWARFModuleUnit final : public LoadedFile {
}
};

static_assert(IsTriviallyDestructible<DWARFModuleUnit>::value,
"DWARFModuleUnits are BumpPtrAllocated; the d'tor is not called");

ModuleDecl *ClangImporter::Implementation::loadModuleDWARF(
SourceLoc importLoc, ArrayRef<std::pair<Identifier, SourceLoc>> path) {
// There's no importing from debug info if no importer is installed.
Expand Down
2 changes: 2 additions & 0 deletions lib/FrontendTool/FrontendTool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,8 @@ static bool emitLoadedModuleTraceIfNeeded(ModuleDecl *mainModule,
for (auto &module : ctxt.LoadedModules) {
ModuleDecl *loadedDecl = module.second;
assert(loadedDecl && "Expected loaded module to be non-null.");
if (loadedDecl == mainModule)
continue;
assert(!loadedDecl->getModuleFilename().empty()
&& "Don't know how to handle modules with empty names.");
pathToModuleDecl.insert(
Expand Down
10 changes: 4 additions & 6 deletions lib/Serialization/Deserialization.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2254,7 +2254,7 @@ class swift::DeclDeserializer {

Identifier privateDiscriminator;
unsigned localDiscriminator = 0;
Identifier filenameForPrivate;
StringRef filenameForPrivate;

void AddAttribute(DeclAttribute *Attr) {
// Advance the linked list.
Expand Down Expand Up @@ -2308,10 +2308,8 @@ class swift::DeclDeserializer {
if (localDiscriminator != 0)
value->setLocalDiscriminator(localDiscriminator);

if (!filenameForPrivate.empty()) {
auto *loadedFile = cast<LoadedFile>(MF.getFile());
loadedFile->addFilenameForPrivateDecl(value, filenameForPrivate);
}
if (!filenameForPrivate.empty())
MF.FilenamesForPrivateValues[value] = filenameForPrivate;
}

decl->setValidationToChecked();
Expand Down Expand Up @@ -4202,7 +4200,7 @@ llvm::Error DeclDeserializer::deserializeDeclAttributes() {
} else if (recordID == decls_block::FILENAME_FOR_PRIVATE) {
IdentifierID filenameID;
decls_block::FilenameForPrivateLayout::readRecord(scratch, filenameID);
filenameForPrivate = MF.getIdentifier(filenameID);
filenameForPrivate = MF.getIdentifierText(filenameID);
} else {
return llvm::Error::success();
}
Expand Down
6 changes: 4 additions & 2 deletions lib/Serialization/ModuleFile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ using namespace swift::serialization;
using namespace llvm::support;
using llvm::Expected;

static_assert(IsTriviallyDestructible<SerializedASTFile>::value,
"SerializedASTFiles are BumpPtrAllocated; d'tors are not called");

static bool checkModuleSignature(llvm::BitstreamCursor &cursor,
ArrayRef<unsigned char> signature) {
for (unsigned char byte : signature)
Expand Down Expand Up @@ -1352,8 +1355,7 @@ ModuleFile::ModuleFile(
break;
}
case input_block::PARSEABLE_INTERFACE_PATH: {
if (extInfo)
extInfo->setParseableInterface(blobData);
ModuleInterfacePath = blobData;
break;
}
default:
Expand Down
6 changes: 5 additions & 1 deletion lib/Serialization/SerializedModuleLoader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -548,7 +548,6 @@ FileUnit *SerializedModuleLoaderBase::loadAST(
// We've loaded the file. Now try to bring it into the AST.
auto fileUnit = new (Ctx) SerializedASTFile(M, *loadedModuleFile,
extendedInfo.isSIB());
fileUnit->setParseableInterface(extendedInfo.getParseableInterface());
M.addFile(*fileUnit);
if (extendedInfo.isTestable())
M.setTestingEnabled();
Expand Down Expand Up @@ -956,6 +955,11 @@ void SerializedASTFile::lookupValue(ModuleDecl::AccessPathTy accessPath,
File.lookupValue(name, results);
}

StringRef
SerializedASTFile::getFilenameForPrivateDecl(const ValueDecl *decl) const {
return File.FilenamesForPrivateValues.lookup(decl);
}

TypeDecl *SerializedASTFile::lookupLocalType(llvm::StringRef MangledName) const{
return File.lookupLocalType(MangledName);
}
Expand Down