Revert "Modules: Cache PCMs in memory and avoid a use-after-free"

This reverts commit r298165, as it broke the ARM builds.

llvm-svn: 298185
This commit is contained in:
Renato Golin 2017-03-18 12:31:32 +00:00
parent e6ff30b696
commit f1966cf646
34 changed files with 60 additions and 478 deletions

View File

@ -176,11 +176,6 @@ def warn_duplicate_module_file_extension : Warning<
"duplicate module file extension block name '%0'">, "duplicate module file extension block name '%0'">,
InGroup<ModuleFileExtension>; InGroup<ModuleFileExtension>;
def warn_module_system_bit_conflict : Warning<
"module file '%0' was validated as a system module and is now being imported "
"as a non-system module; any difference in diagnostic options will be ignored">,
InGroup<ModuleConflict>;
} // let CategoryName } // let CategoryName
} // let Component } // let Component

View File

@ -1,80 +0,0 @@
//===- MemoryBufferCache.h - Cache for loaded memory buffers ----*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_BASIC_MEMORYBUFFERCACHE_H
#define LLVM_CLANG_BASIC_MEMORYBUFFERCACHE_H
#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "llvm/ADT/StringMap.h"
#include <memory>
namespace llvm {
class MemoryBuffer;
} // end namespace llvm
namespace clang {
/// Manage memory buffers across multiple users.
///
/// Ensures that multiple users have a consistent view of each buffer. This is
/// used by \a CompilerInstance when building PCMs to ensure that each \a
/// ModuleManager sees the same files.
///
/// \a finalizeCurrentBuffers() should be called before creating a new user.
/// This locks in the current buffers, ensuring that no buffer that has already
/// been accessed can be purged, preventing use-after-frees.
class MemoryBufferCache : public llvm::RefCountedBase<MemoryBufferCache> {
struct BufferEntry {
std::unique_ptr<llvm::MemoryBuffer> Buffer;
/// Track the timeline of when this was added to the cache.
unsigned Index;
};
/// Cache of buffers.
llvm::StringMap<BufferEntry> Buffers;
/// Monotonically increasing index.
unsigned NextIndex = 0;
/// Bumped to prevent "older" buffers from being removed.
unsigned FirstRemovableIndex = 0;
public:
/// Store the Buffer under the Filename.
///
/// \pre There is not already buffer is not already in the cache.
/// \return a reference to the buffer as a convenience.
llvm::MemoryBuffer &addBuffer(llvm::StringRef Filename,
std::unique_ptr<llvm::MemoryBuffer> Buffer);
/// Try to remove a buffer from the cache.
///
/// \return false on success, iff \c !isBufferFinal().
bool tryToRemoveBuffer(llvm::StringRef Filename);
/// Get a pointer to the buffer if it exists; else nullptr.
llvm::MemoryBuffer *lookupBuffer(llvm::StringRef Filename);
/// Check whether the buffer is final.
///
/// \return true iff \a finalizeCurrentBuffers() has been called since the
/// buffer was added. This prevents buffers from being removed.
bool isBufferFinal(llvm::StringRef Filename);
/// Finalize the current buffers in the cache.
///
/// Should be called when creating a new user to ensure previous uses aren't
/// invalidated.
void finalizeCurrentBuffers();
};
} // end namespace clang
#endif // LLVM_CLANG_BASIC_MEMORYBUFFERCACHE_H

View File

@ -51,7 +51,6 @@ class DiagnosticsEngine;
class FileEntry; class FileEntry;
class FileManager; class FileManager;
class HeaderSearch; class HeaderSearch;
class MemoryBufferCache;
class Preprocessor; class Preprocessor;
class PCHContainerOperations; class PCHContainerOperations;
class PCHContainerReader; class PCHContainerReader;
@ -85,7 +84,6 @@ private:
IntrusiveRefCntPtr<DiagnosticsEngine> Diagnostics; IntrusiveRefCntPtr<DiagnosticsEngine> Diagnostics;
IntrusiveRefCntPtr<FileManager> FileMgr; IntrusiveRefCntPtr<FileManager> FileMgr;
IntrusiveRefCntPtr<SourceManager> SourceMgr; IntrusiveRefCntPtr<SourceManager> SourceMgr;
IntrusiveRefCntPtr<MemoryBufferCache> PCMCache;
std::unique_ptr<HeaderSearch> HeaderInfo; std::unique_ptr<HeaderSearch> HeaderInfo;
IntrusiveRefCntPtr<TargetInfo> Target; IntrusiveRefCntPtr<TargetInfo> Target;
std::shared_ptr<Preprocessor> PP; std::shared_ptr<Preprocessor> PP;

View File

@ -44,7 +44,6 @@ class ExternalASTSource;
class FileEntry; class FileEntry;
class FileManager; class FileManager;
class FrontendAction; class FrontendAction;
class MemoryBufferCache;
class Module; class Module;
class Preprocessor; class Preprocessor;
class Sema; class Sema;
@ -91,9 +90,6 @@ class CompilerInstance : public ModuleLoader {
/// The source manager. /// The source manager.
IntrusiveRefCntPtr<SourceManager> SourceMgr; IntrusiveRefCntPtr<SourceManager> SourceMgr;
/// The cache of PCM files.
IntrusiveRefCntPtr<MemoryBufferCache> PCMCache;
/// The preprocessor. /// The preprocessor.
std::shared_ptr<Preprocessor> PP; std::shared_ptr<Preprocessor> PP;
@ -182,7 +178,7 @@ public:
explicit CompilerInstance( explicit CompilerInstance(
std::shared_ptr<PCHContainerOperations> PCHContainerOps = std::shared_ptr<PCHContainerOperations> PCHContainerOps =
std::make_shared<PCHContainerOperations>(), std::make_shared<PCHContainerOperations>(),
MemoryBufferCache *SharedPCMCache = nullptr); bool BuildingModule = false);
~CompilerInstance() override; ~CompilerInstance() override;
/// @name High-Level Operations /// @name High-Level Operations
@ -787,8 +783,6 @@ public:
} }
void setExternalSemaSource(IntrusiveRefCntPtr<ExternalSemaSource> ESS); void setExternalSemaSource(IntrusiveRefCntPtr<ExternalSemaSource> ESS);
MemoryBufferCache &getPCMCache() const { return *PCMCache; }
}; };
} // end namespace clang } // end namespace clang

View File

@ -47,7 +47,6 @@ class ExternalPreprocessorSource;
class FileManager; class FileManager;
class FileEntry; class FileEntry;
class HeaderSearch; class HeaderSearch;
class MemoryBufferCache;
class PragmaNamespace; class PragmaNamespace;
class PragmaHandler; class PragmaHandler;
class CommentHandler; class CommentHandler;
@ -103,7 +102,6 @@ class Preprocessor {
const TargetInfo *AuxTarget; const TargetInfo *AuxTarget;
FileManager &FileMgr; FileManager &FileMgr;
SourceManager &SourceMgr; SourceManager &SourceMgr;
MemoryBufferCache &PCMCache;
std::unique_ptr<ScratchBuffer> ScratchBuf; std::unique_ptr<ScratchBuffer> ScratchBuf;
HeaderSearch &HeaderInfo; HeaderSearch &HeaderInfo;
ModuleLoader &TheModuleLoader; ModuleLoader &TheModuleLoader;
@ -654,7 +652,6 @@ class Preprocessor {
public: public:
Preprocessor(std::shared_ptr<PreprocessorOptions> PPOpts, Preprocessor(std::shared_ptr<PreprocessorOptions> PPOpts,
DiagnosticsEngine &diags, LangOptions &opts, SourceManager &SM, DiagnosticsEngine &diags, LangOptions &opts, SourceManager &SM,
MemoryBufferCache &PCMCache,
HeaderSearch &Headers, ModuleLoader &TheModuleLoader, HeaderSearch &Headers, ModuleLoader &TheModuleLoader,
IdentifierInfoLookup *IILookup = nullptr, IdentifierInfoLookup *IILookup = nullptr,
bool OwnsHeaderSearch = false, bool OwnsHeaderSearch = false,
@ -694,7 +691,6 @@ public:
const TargetInfo *getAuxTargetInfo() const { return AuxTarget; } const TargetInfo *getAuxTargetInfo() const { return AuxTarget; }
FileManager &getFileManager() const { return FileMgr; } FileManager &getFileManager() const { return FileMgr; }
SourceManager &getSourceManager() const { return SourceMgr; } SourceManager &getSourceManager() const { return SourceMgr; }
MemoryBufferCache &getPCMCache() const { return PCMCache; }
HeaderSearch &getHeaderSearchInfo() const { return HeaderInfo; } HeaderSearch &getHeaderSearchInfo() const { return HeaderInfo; }
IdentifierTable &getIdentifierTable() { return Identifiers; } IdentifierTable &getIdentifierTable() { return Identifiers; }

View File

@ -408,9 +408,6 @@ private:
/// \brief The module manager which manages modules and their dependencies /// \brief The module manager which manages modules and their dependencies
ModuleManager ModuleMgr; ModuleManager ModuleMgr;
/// The cache that manages memory buffers for PCM files.
MemoryBufferCache &PCMCache;
/// \brief A dummy identifier resolver used to merge TU-scope declarations in /// \brief A dummy identifier resolver used to merge TU-scope declarations in
/// C, for the cases where we don't have a Sema object to provide a real /// C, for the cases where we don't have a Sema object to provide a real
/// identifier resolver. /// identifier resolver.

View File

@ -54,7 +54,6 @@ class MacroInfo;
class OpaqueValueExpr; class OpaqueValueExpr;
class OpenCLOptions; class OpenCLOptions;
class ASTReader; class ASTReader;
class MemoryBufferCache;
class Module; class Module;
class ModuleFileExtension; class ModuleFileExtension;
class ModuleFileExtensionWriter; class ModuleFileExtensionWriter;
@ -110,9 +109,6 @@ private:
/// The buffer associated with the bitstream. /// The buffer associated with the bitstream.
const SmallVectorImpl<char> &Buffer; const SmallVectorImpl<char> &Buffer;
/// \brief The PCM manager which manages memory buffers for pcm files.
MemoryBufferCache &PCMCache;
/// \brief The ASTContext we're writing. /// \brief The ASTContext we're writing.
ASTContext *Context = nullptr; ASTContext *Context = nullptr;
@ -516,7 +512,6 @@ public:
/// \brief Create a new precompiled header writer that outputs to /// \brief Create a new precompiled header writer that outputs to
/// the given bitstream. /// the given bitstream.
ASTWriter(llvm::BitstreamWriter &Stream, SmallVectorImpl<char> &Buffer, ASTWriter(llvm::BitstreamWriter &Stream, SmallVectorImpl<char> &Buffer,
MemoryBufferCache &PCMCache,
ArrayRef<std::shared_ptr<ModuleFileExtension>> Extensions, ArrayRef<std::shared_ptr<ModuleFileExtension>> Extensions,
bool IncludeTimestamps = true); bool IncludeTimestamps = true);
~ASTWriter() override; ~ASTWriter() override;

View File

@ -163,9 +163,9 @@ public:
/// \brief The generation of which this module file is a part. /// \brief The generation of which this module file is a part.
unsigned Generation; unsigned Generation;
/// The memory buffer that stores the data associated with /// \brief The memory buffer that stores the data associated with
/// this AST file, owned by the PCMCache in the ModuleManager. /// this AST file.
llvm::MemoryBuffer *Buffer; std::unique_ptr<llvm::MemoryBuffer> Buffer;
/// \brief The size of this file, in bits. /// \brief The size of this file, in bits.
uint64_t SizeInBits = 0; uint64_t SizeInBits = 0;

View File

@ -24,7 +24,6 @@
namespace clang { namespace clang {
class GlobalModuleIndex; class GlobalModuleIndex;
class MemoryBufferCache;
class ModuleMap; class ModuleMap;
class PCHContainerReader; class PCHContainerReader;
@ -52,9 +51,6 @@ class ModuleManager {
/// FileEntry *. /// FileEntry *.
FileManager &FileMgr; FileManager &FileMgr;
/// Cache of PCM files.
IntrusiveRefCntPtr<MemoryBufferCache> PCMCache;
/// \brief Knows how to unwrap module containers. /// \brief Knows how to unwrap module containers.
const PCHContainerReader &PCHContainerRdr; const PCHContainerReader &PCHContainerRdr;
@ -127,7 +123,7 @@ public:
ModuleReverseIterator; ModuleReverseIterator;
typedef std::pair<uint32_t, StringRef> ModuleOffset; typedef std::pair<uint32_t, StringRef> ModuleOffset;
explicit ModuleManager(FileManager &FileMgr, MemoryBufferCache &PCMCache, explicit ModuleManager(FileManager &FileMgr,
const PCHContainerReader &PCHContainerRdr); const PCHContainerReader &PCHContainerRdr);
~ModuleManager(); ~ModuleManager();
@ -294,8 +290,6 @@ public:
/// \brief View the graphviz representation of the module graph. /// \brief View the graphviz representation of the module graph.
void viewGraph(); void viewGraph();
MemoryBufferCache &getPCMCache() const { return *PCMCache; }
}; };
} } // end namespace clang::serialization } } // end namespace clang::serialization

View File

@ -74,7 +74,6 @@ add_clang_library(clangBasic
FileSystemStatCache.cpp FileSystemStatCache.cpp
IdentifierTable.cpp IdentifierTable.cpp
LangOptions.cpp LangOptions.cpp
MemoryBufferCache.cpp
Module.cpp Module.cpp
ObjCRuntime.cpp ObjCRuntime.cpp
OpenMPKinds.cpp OpenMPKinds.cpp

View File

@ -1,48 +0,0 @@
//===- MemoryBufferCache.cpp - Cache for loaded memory buffers ------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "clang/Basic/MemoryBufferCache.h"
#include "llvm/Support/MemoryBuffer.h"
using namespace clang;
llvm::MemoryBuffer &
MemoryBufferCache::addBuffer(llvm::StringRef Filename,
std::unique_ptr<llvm::MemoryBuffer> Buffer) {
auto Insertion =
Buffers.insert({Filename, BufferEntry{std::move(Buffer), NextIndex++}});
assert(Insertion.second && "Already has a buffer");
return *Insertion.first->second.Buffer;
}
llvm::MemoryBuffer *MemoryBufferCache::lookupBuffer(llvm::StringRef Filename) {
auto I = Buffers.find(Filename);
if (I == Buffers.end())
return nullptr;
return I->second.Buffer.get();
}
bool MemoryBufferCache::isBufferFinal(llvm::StringRef Filename) {
auto I = Buffers.find(Filename);
if (I == Buffers.end())
return false;
return I->second.Index < FirstRemovableIndex;
}
bool MemoryBufferCache::tryToRemoveBuffer(llvm::StringRef Filename) {
auto I = Buffers.find(Filename);
assert(I != Buffers.end() && "No buffer to remove...");
if (I->second.Index < FirstRemovableIndex)
return true;
Buffers.erase(I);
return false;
}
void MemoryBufferCache::finalizeCurrentBuffers() { FirstRemovableIndex = NextIndex; }

View File

@ -18,7 +18,6 @@
#include "clang/AST/StmtVisitor.h" #include "clang/AST/StmtVisitor.h"
#include "clang/AST/TypeOrdering.h" #include "clang/AST/TypeOrdering.h"
#include "clang/Basic/Diagnostic.h" #include "clang/Basic/Diagnostic.h"
#include "clang/Basic/MemoryBufferCache.h"
#include "clang/Basic/TargetInfo.h" #include "clang/Basic/TargetInfo.h"
#include "clang/Basic/TargetOptions.h" #include "clang/Basic/TargetOptions.h"
#include "clang/Basic/VirtualFileSystem.h" #include "clang/Basic/VirtualFileSystem.h"
@ -186,8 +185,7 @@ struct ASTUnit::ASTWriterData {
llvm::BitstreamWriter Stream; llvm::BitstreamWriter Stream;
ASTWriter Writer; ASTWriter Writer;
ASTWriterData(MemoryBufferCache &PCMCache) ASTWriterData() : Stream(Buffer), Writer(Stream, Buffer, {}) {}
: Stream(Buffer), Writer(Stream, Buffer, PCMCache, {}) {}
}; };
void ASTUnit::clearFileLevelDecls() { void ASTUnit::clearFileLevelDecls() {
@ -683,7 +681,6 @@ std::unique_ptr<ASTUnit> ASTUnit::LoadFromASTFile(
AST->SourceMgr = new SourceManager(AST->getDiagnostics(), AST->SourceMgr = new SourceManager(AST->getDiagnostics(),
AST->getFileManager(), AST->getFileManager(),
UserFilesAreVolatile); UserFilesAreVolatile);
AST->PCMCache = new MemoryBufferCache;
AST->HSOpts = std::make_shared<HeaderSearchOptions>(); AST->HSOpts = std::make_shared<HeaderSearchOptions>();
AST->HSOpts->ModuleFormat = PCHContainerRdr.getFormat(); AST->HSOpts->ModuleFormat = PCHContainerRdr.getFormat();
AST->HeaderInfo.reset(new HeaderSearch(AST->HSOpts, AST->HeaderInfo.reset(new HeaderSearch(AST->HSOpts,
@ -704,7 +701,7 @@ std::unique_ptr<ASTUnit> ASTUnit::LoadFromASTFile(
AST->PP = std::make_shared<Preprocessor>( AST->PP = std::make_shared<Preprocessor>(
std::move(PPOpts), AST->getDiagnostics(), AST->ASTFileLangOpts, std::move(PPOpts), AST->getDiagnostics(), AST->ASTFileLangOpts,
AST->getSourceManager(), *AST->PCMCache, HeaderInfo, *AST, AST->getSourceManager(), HeaderInfo, *AST,
/*IILookup=*/nullptr, /*IILookup=*/nullptr,
/*OwnsHeaderSearch=*/false); /*OwnsHeaderSearch=*/false);
Preprocessor &PP = *AST->PP; Preprocessor &PP = *AST->PP;
@ -1730,7 +1727,6 @@ ASTUnit::create(std::shared_ptr<CompilerInvocation> CI,
AST->UserFilesAreVolatile = UserFilesAreVolatile; AST->UserFilesAreVolatile = UserFilesAreVolatile;
AST->SourceMgr = new SourceManager(AST->getDiagnostics(), *AST->FileMgr, AST->SourceMgr = new SourceManager(AST->getDiagnostics(), *AST->FileMgr,
UserFilesAreVolatile); UserFilesAreVolatile);
AST->PCMCache = new MemoryBufferCache;
return AST; return AST;
} }
@ -2001,7 +1997,6 @@ ASTUnit *ASTUnit::LoadFromCommandLine(
if (!VFS) if (!VFS)
return nullptr; return nullptr;
AST->FileMgr = new FileManager(AST->FileSystemOpts, VFS); AST->FileMgr = new FileManager(AST->FileSystemOpts, VFS);
AST->PCMCache = new MemoryBufferCache;
AST->OnlyLocalDecls = OnlyLocalDecls; AST->OnlyLocalDecls = OnlyLocalDecls;
AST->CaptureDiagnostics = CaptureDiagnostics; AST->CaptureDiagnostics = CaptureDiagnostics;
AST->TUKind = TUKind; AST->TUKind = TUKind;
@ -2013,7 +2008,7 @@ ASTUnit *ASTUnit::LoadFromCommandLine(
AST->StoredDiagnostics.swap(StoredDiagnostics); AST->StoredDiagnostics.swap(StoredDiagnostics);
AST->Invocation = CI; AST->Invocation = CI;
if (ForSerialization) if (ForSerialization)
AST->WriterData.reset(new ASTWriterData(*AST->PCMCache)); AST->WriterData.reset(new ASTWriterData());
// Zero out now to ease cleanup during crash recovery. // Zero out now to ease cleanup during crash recovery.
CI = nullptr; CI = nullptr;
Diags = nullptr; Diags = nullptr;
@ -2528,8 +2523,7 @@ bool ASTUnit::serialize(raw_ostream &OS) {
SmallString<128> Buffer; SmallString<128> Buffer;
llvm::BitstreamWriter Stream(Buffer); llvm::BitstreamWriter Stream(Buffer);
MemoryBufferCache PCMCache; ASTWriter Writer(Stream, Buffer, {});
ASTWriter Writer(Stream, Buffer, PCMCache, {});
return serializeUnit(Writer, Buffer, getSema(), hasErrors, OS); return serializeUnit(Writer, Buffer, getSema(), hasErrors, OS);
} }

View File

@ -13,7 +13,6 @@
#include "clang/AST/Decl.h" #include "clang/AST/Decl.h"
#include "clang/Basic/Diagnostic.h" #include "clang/Basic/Diagnostic.h"
#include "clang/Basic/FileManager.h" #include "clang/Basic/FileManager.h"
#include "clang/Basic/MemoryBufferCache.h"
#include "clang/Basic/SourceManager.h" #include "clang/Basic/SourceManager.h"
#include "clang/Basic/TargetInfo.h" #include "clang/Basic/TargetInfo.h"
#include "clang/Basic/Version.h" #include "clang/Basic/Version.h"
@ -56,15 +55,9 @@ using namespace clang;
CompilerInstance::CompilerInstance( CompilerInstance::CompilerInstance(
std::shared_ptr<PCHContainerOperations> PCHContainerOps, std::shared_ptr<PCHContainerOperations> PCHContainerOps,
MemoryBufferCache *SharedPCMCache) bool BuildingModule)
: ModuleLoader(/* BuildingModule = */ SharedPCMCache), : ModuleLoader(BuildingModule), Invocation(new CompilerInvocation()),
Invocation(new CompilerInvocation()), ThePCHContainerOperations(std::move(PCHContainerOps)) {}
PCMCache(SharedPCMCache ? SharedPCMCache : new MemoryBufferCache),
ThePCHContainerOperations(std::move(PCHContainerOps)) {
// Don't allow this to invalidate buffers in use by others.
if (SharedPCMCache)
getPCMCache().finalizeCurrentBuffers();
}
CompilerInstance::~CompilerInstance() { CompilerInstance::~CompilerInstance() {
assert(OutputFiles.empty() && "Still output files in flight?"); assert(OutputFiles.empty() && "Still output files in flight?");
@ -135,8 +128,6 @@ IntrusiveRefCntPtr<ASTReader> CompilerInstance::getModuleManager() const {
return ModuleManager; return ModuleManager;
} }
void CompilerInstance::setModuleManager(IntrusiveRefCntPtr<ASTReader> Reader) { void CompilerInstance::setModuleManager(IntrusiveRefCntPtr<ASTReader> Reader) {
assert(PCMCache.get() == &Reader->getModuleManager().getPCMCache() &&
"Expected ASTReader to use the same PCM cache");
ModuleManager = std::move(Reader); ModuleManager = std::move(Reader);
} }
@ -379,7 +370,7 @@ void CompilerInstance::createPreprocessor(TranslationUnitKind TUKind) {
getDiagnostics(), getLangOpts(), &getTarget()); getDiagnostics(), getLangOpts(), &getTarget());
PP = std::make_shared<Preprocessor>( PP = std::make_shared<Preprocessor>(
Invocation->getPreprocessorOptsPtr(), getDiagnostics(), getLangOpts(), Invocation->getPreprocessorOptsPtr(), getDiagnostics(), getLangOpts(),
getSourceManager(), getPCMCache(), *HeaderInfo, *this, PTHMgr, getSourceManager(), *HeaderInfo, *this, PTHMgr,
/*OwnsHeaderSearch=*/true, TUKind); /*OwnsHeaderSearch=*/true, TUKind);
PP->Initialize(getTarget(), getAuxTarget()); PP->Initialize(getTarget(), getAuxTarget());
@ -1082,11 +1073,9 @@ static bool compileModuleImpl(CompilerInstance &ImportingInstance,
Invocation->getModuleHash() && "Module hash mismatch!"); Invocation->getModuleHash() && "Module hash mismatch!");
// Construct a compiler instance that will be used to actually create the // Construct a compiler instance that will be used to actually create the
// module. Since we're sharing a PCMCache, // module.
// CompilerInstance::CompilerInstance is responsible for finalizing the
// buffers to prevent use-after-frees.
CompilerInstance Instance(ImportingInstance.getPCHContainerOperations(), CompilerInstance Instance(ImportingInstance.getPCHContainerOperations(),
&ImportingInstance.getPreprocessor().getPCMCache()); /*BuildingModule=*/true);
auto &Inv = *Invocation; auto &Inv = *Invocation;
Instance.setInvocation(std::move(Invocation)); Instance.setInvocation(std::move(Invocation));

View File

@ -70,15 +70,15 @@ ExternalPreprocessorSource::~ExternalPreprocessorSource() { }
Preprocessor::Preprocessor(std::shared_ptr<PreprocessorOptions> PPOpts, Preprocessor::Preprocessor(std::shared_ptr<PreprocessorOptions> PPOpts,
DiagnosticsEngine &diags, LangOptions &opts, DiagnosticsEngine &diags, LangOptions &opts,
SourceManager &SM, MemoryBufferCache &PCMCache, SourceManager &SM, HeaderSearch &Headers,
HeaderSearch &Headers, ModuleLoader &TheModuleLoader, ModuleLoader &TheModuleLoader,
IdentifierInfoLookup *IILookup, bool OwnsHeaders, IdentifierInfoLookup *IILookup, bool OwnsHeaders,
TranslationUnitKind TUKind) TranslationUnitKind TUKind)
: PPOpts(std::move(PPOpts)), Diags(&diags), LangOpts(opts), Target(nullptr), : PPOpts(std::move(PPOpts)), Diags(&diags), LangOpts(opts), Target(nullptr),
AuxTarget(nullptr), FileMgr(Headers.getFileMgr()), SourceMgr(SM), AuxTarget(nullptr), FileMgr(Headers.getFileMgr()), SourceMgr(SM),
PCMCache(PCMCache), ScratchBuf(new ScratchBuffer(SourceMgr)), ScratchBuf(new ScratchBuffer(SourceMgr)), HeaderInfo(Headers),
HeaderInfo(Headers), TheModuleLoader(TheModuleLoader), TheModuleLoader(TheModuleLoader), ExternalSource(nullptr),
ExternalSource(nullptr), Identifiers(opts, IILookup), Identifiers(opts, IILookup),
PragmaHandlers(new PragmaNamespace(StringRef())), PragmaHandlers(new PragmaNamespace(StringRef())),
IncrementalProcessing(false), TUKind(TUKind), CodeComplete(nullptr), IncrementalProcessing(false), TUKind(TUKind), CodeComplete(nullptr),
CodeCompletionFile(nullptr), CodeCompletionOffset(0), CodeCompletionFile(nullptr), CodeCompletionOffset(0),

View File

@ -37,7 +37,6 @@
#include "clang/Basic/FileManager.h" #include "clang/Basic/FileManager.h"
#include "clang/Basic/FileSystemOptions.h" #include "clang/Basic/FileSystemOptions.h"
#include "clang/Basic/LangOptions.h" #include "clang/Basic/LangOptions.h"
#include "clang/Basic/MemoryBufferCache.h"
#include "clang/Basic/ObjCRuntime.h" #include "clang/Basic/ObjCRuntime.h"
#include "clang/Basic/OperatorKinds.h" #include "clang/Basic/OperatorKinds.h"
#include "clang/Basic/Sanitizers.h" #include "clang/Basic/Sanitizers.h"
@ -464,30 +463,6 @@ static bool checkDiagnosticMappings(DiagnosticsEngine &StoredDiags,
return checkDiagnosticGroupMappings(StoredDiags, Diags, Complain); return checkDiagnosticGroupMappings(StoredDiags, Diags, Complain);
} }
/// Return the top import module if it is implicit, nullptr otherwise.
static Module *getTopImportImplicitModule(ModuleManager &ModuleMgr,
Preprocessor &PP) {
// If the original import came from a file explicitly generated by the user,
// don't check the diagnostic mappings.
// FIXME: currently this is approximated by checking whether this is not a
// module import of an implicitly-loaded module file.
// Note: ModuleMgr.rbegin() may not be the current module, but it must be in
// the transitive closure of its imports, since unrelated modules cannot be
// imported until after this module finishes validation.
ModuleFile *TopImport = &*ModuleMgr.rbegin();
while (!TopImport->ImportedBy.empty())
TopImport = TopImport->ImportedBy[0];
if (TopImport->Kind != MK_ImplicitModule)
return nullptr;
StringRef ModuleName = TopImport->ModuleName;
assert(!ModuleName.empty() && "diagnostic options read before module name");
Module *M = PP.getHeaderSearchInfo().lookupModule(ModuleName);
assert(M && "missing module");
return M;
}
bool PCHValidator::ReadDiagnosticOptions( bool PCHValidator::ReadDiagnosticOptions(
IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts, bool Complain) { IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts, bool Complain) {
DiagnosticsEngine &ExistingDiags = PP.getDiagnostics(); DiagnosticsEngine &ExistingDiags = PP.getDiagnostics();
@ -501,14 +476,28 @@ bool PCHValidator::ReadDiagnosticOptions(
ModuleManager &ModuleMgr = Reader.getModuleManager(); ModuleManager &ModuleMgr = Reader.getModuleManager();
assert(ModuleMgr.size() >= 1 && "what ASTFile is this then"); assert(ModuleMgr.size() >= 1 && "what ASTFile is this then");
Module *TopM = getTopImportImplicitModule(ModuleMgr, PP); // If the original import came from a file explicitly generated by the user,
if (!TopM) // don't check the diagnostic mappings.
// FIXME: currently this is approximated by checking whether this is not a
// module import of an implicitly-loaded module file.
// Note: ModuleMgr.rbegin() may not be the current module, but it must be in
// the transitive closure of its imports, since unrelated modules cannot be
// imported until after this module finishes validation.
ModuleFile *TopImport = &*ModuleMgr.rbegin();
while (!TopImport->ImportedBy.empty())
TopImport = TopImport->ImportedBy[0];
if (TopImport->Kind != MK_ImplicitModule)
return false; return false;
StringRef ModuleName = TopImport->ModuleName;
assert(!ModuleName.empty() && "diagnostic options read before module name");
Module *M = PP.getHeaderSearchInfo().lookupModule(ModuleName);
assert(M && "missing module");
// FIXME: if the diagnostics are incompatible, save a DiagnosticOptions that // FIXME: if the diagnostics are incompatible, save a DiagnosticOptions that
// contains the union of their flags. // contains the union of their flags.
return checkDiagnosticMappings(*Diags, ExistingDiags, TopM->IsSystem, return checkDiagnosticMappings(*Diags, ExistingDiags, M->IsSystem, Complain);
Complain);
} }
/// \brief Collect the macro definitions provided by the given preprocessor /// \brief Collect the macro definitions provided by the given preprocessor
@ -4075,41 +4064,12 @@ ASTReader::readUnhashedControlBlock(ModuleFile &F, bool WasImportedBy,
Listener.get(), Listener.get(),
WasImportedBy ? false : HSOpts.ModulesValidateDiagnosticOptions); WasImportedBy ? false : HSOpts.ModulesValidateDiagnosticOptions);
// If F was directly imported by another module, it's implicitly validated by
// the importing module.
if (DisableValidation || WasImportedBy || if (DisableValidation || WasImportedBy ||
(AllowConfigurationMismatch && Result == ConfigurationMismatch)) (AllowConfigurationMismatch && Result == ConfigurationMismatch))
return Success; return Success;
if (Result == Failure) { if (Result == Failure)
Error("malformed block record in AST file"); Error("malformed block record in AST file");
return Failure;
}
if (Result == OutOfDate && F.Kind == MK_ImplicitModule) {
// If this module has already been finalized in the PCMCache, we're stuck
// with it; we can only load a single version of each module.
//
// This can happen when a module is imported in two contexts: in one, as a
// user module; in another, as a system module (due to an import from
// another module marked with the [system] flag). It usually indicates a
// bug in the module map: this module should also be marked with [system].
//
// If -Wno-system-headers (the default), and the first import is as a
// system module, then validation will fail during the as-user import,
// since -Werror flags won't have been validated. However, it's reasonable
// to treat this consistently as a system module.
//
// If -Wsystem-headers, the PCM on disk was built with
// -Wno-system-headers, and the first import is as a user module, then
// validation will fail during the as-system import since the PCM on disk
// doesn't guarantee that -Werror was respected. However, the -Werror
// flags were checked during the initial as-user import.
if (PCMCache.isBufferFinal(F.FileName)) {
Diag(diag::warn_module_system_bit_conflict) << F.FileName;
return Success;
}
}
return Result; return Result;
} }
@ -4162,7 +4122,7 @@ ASTReader::ASTReadResult ASTReader::readUnhashedControlBlockImpl(
if (Listener && ValidateDiagnosticOptions && if (Listener && ValidateDiagnosticOptions &&
!AllowCompatibleConfigurationMismatch && !AllowCompatibleConfigurationMismatch &&
ParseDiagnosticOptions(Record, Complain, *Listener)) ParseDiagnosticOptions(Record, Complain, *Listener))
Result = OutOfDate; // Don't return early. Read the signature. return OutOfDate;
break; break;
} }
case DIAG_PRAGMA_MAPPINGS: case DIAG_PRAGMA_MAPPINGS:
@ -7341,7 +7301,7 @@ LLVM_DUMP_METHOD void ASTReader::dump() {
/// by heap-backed versus mmap'ed memory. /// by heap-backed versus mmap'ed memory.
void ASTReader::getMemoryBufferSizes(MemoryBufferSizes &sizes) const { void ASTReader::getMemoryBufferSizes(MemoryBufferSizes &sizes) const {
for (ModuleFile &I : ModuleMgr) { for (ModuleFile &I : ModuleMgr) {
if (llvm::MemoryBuffer *buf = I.Buffer) { if (llvm::MemoryBuffer *buf = I.Buffer.get()) {
size_t bytes = buf->getBufferSize(); size_t bytes = buf->getBufferSize();
switch (buf->getBufferKind()) { switch (buf->getBufferKind()) {
case llvm::MemoryBuffer::MemoryBuffer_Malloc: case llvm::MemoryBuffer::MemoryBuffer_Malloc:
@ -9668,10 +9628,8 @@ ASTReader::ASTReader(Preprocessor &PP, ASTContext &Context,
: cast<ASTReaderListener>(new PCHValidator(PP, *this))), : cast<ASTReaderListener>(new PCHValidator(PP, *this))),
SourceMgr(PP.getSourceManager()), FileMgr(PP.getFileManager()), SourceMgr(PP.getSourceManager()), FileMgr(PP.getFileManager()),
PCHContainerRdr(PCHContainerRdr), Diags(PP.getDiagnostics()), PP(PP), PCHContainerRdr(PCHContainerRdr), Diags(PP.getDiagnostics()), PP(PP),
Context(Context), Context(Context), ModuleMgr(PP.getFileManager(), PCHContainerRdr),
ModuleMgr(PP.getFileManager(), PP.getPCMCache(), PCHContainerRdr), DummyIdResolver(PP), ReadTimer(std::move(ReadTimer)), isysroot(isysroot),
PCMCache(PP.getPCMCache()), DummyIdResolver(PP),
ReadTimer(std::move(ReadTimer)), isysroot(isysroot),
DisableValidation(DisableValidation), DisableValidation(DisableValidation),
AllowASTWithCompilerErrors(AllowASTWithCompilerErrors), AllowASTWithCompilerErrors(AllowASTWithCompilerErrors),
AllowConfigurationMismatch(AllowConfigurationMismatch), AllowConfigurationMismatch(AllowConfigurationMismatch),

View File

@ -35,7 +35,6 @@
#include "clang/Basic/FileSystemOptions.h" #include "clang/Basic/FileSystemOptions.h"
#include "clang/Basic/LLVM.h" #include "clang/Basic/LLVM.h"
#include "clang/Basic/LangOptions.h" #include "clang/Basic/LangOptions.h"
#include "clang/Basic/MemoryBufferCache.h"
#include "clang/Basic/Module.h" #include "clang/Basic/Module.h"
#include "clang/Basic/ObjCRuntime.h" #include "clang/Basic/ObjCRuntime.h"
#include "clang/Basic/SourceManager.h" #include "clang/Basic/SourceManager.h"
@ -4305,11 +4304,10 @@ void ASTWriter::SetSelectorOffset(Selector Sel, uint32_t Offset) {
} }
ASTWriter::ASTWriter(llvm::BitstreamWriter &Stream, ASTWriter::ASTWriter(llvm::BitstreamWriter &Stream,
SmallVectorImpl<char> &Buffer, MemoryBufferCache &PCMCache, SmallVectorImpl<char> &Buffer,
ArrayRef<std::shared_ptr<ModuleFileExtension>> Extensions, ArrayRef<std::shared_ptr<ModuleFileExtension>> Extensions,
bool IncludeTimestamps) bool IncludeTimestamps)
: Stream(Stream), Buffer(Buffer), PCMCache(PCMCache), : Stream(Stream), Buffer(Buffer), IncludeTimestamps(IncludeTimestamps) {
IncludeTimestamps(IncludeTimestamps) {
for (const auto &Ext : Extensions) { for (const auto &Ext : Extensions) {
if (auto Writer = Ext->createExtensionWriter(*this)) if (auto Writer = Ext->createExtensionWriter(*this))
ModuleFileExtensionWriters.push_back(std::move(Writer)); ModuleFileExtensionWriters.push_back(std::move(Writer));
@ -4356,12 +4354,6 @@ ASTFileSignature ASTWriter::WriteAST(Sema &SemaRef,
this->BaseDirectory.clear(); this->BaseDirectory.clear();
WritingAST = false; WritingAST = false;
if (SemaRef.Context.getLangOpts().ImplicitModules && WritingModule) {
// Construct MemoryBuffer and update buffer manager.
PCMCache.addBuffer(OutputFile,
llvm::MemoryBuffer::getMemBufferCopy(
StringRef(Buffer.begin(), Buffer.size())));
}
return Signature; return Signature;
} }

View File

@ -28,8 +28,7 @@ PCHGenerator::PCHGenerator(
bool AllowASTWithErrors, bool IncludeTimestamps) bool AllowASTWithErrors, bool IncludeTimestamps)
: PP(PP), OutputFile(OutputFile), isysroot(isysroot.str()), : PP(PP), OutputFile(OutputFile), isysroot(isysroot.str()),
SemaPtr(nullptr), Buffer(Buffer), Stream(Buffer->Data), SemaPtr(nullptr), Buffer(Buffer), Stream(Buffer->Data),
Writer(Stream, Buffer->Data, PP.getPCMCache(), Extensions, Writer(Stream, Buffer->Data, Extensions, IncludeTimestamps),
IncludeTimestamps),
AllowASTWithErrors(AllowASTWithErrors) { AllowASTWithErrors(AllowASTWithErrors) {
Buffer->IsComplete = false; Buffer->IsComplete = false;
} }

View File

@ -12,7 +12,6 @@
// //
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
#include "clang/Serialization/ModuleManager.h" #include "clang/Serialization/ModuleManager.h"
#include "clang/Basic/MemoryBufferCache.h"
#include "clang/Frontend/PCHContainerOperations.h" #include "clang/Frontend/PCHContainerOperations.h"
#include "clang/Lex/HeaderSearch.h" #include "clang/Lex/HeaderSearch.h"
#include "clang/Lex/ModuleMap.h" #include "clang/Lex/ModuleMap.h"
@ -138,9 +137,7 @@ ModuleManager::addModule(StringRef FileName, ModuleKind Type,
// Load the contents of the module // Load the contents of the module
if (std::unique_ptr<llvm::MemoryBuffer> Buffer = lookupBuffer(FileName)) { if (std::unique_ptr<llvm::MemoryBuffer> Buffer = lookupBuffer(FileName)) {
// The buffer was already provided for us. // The buffer was already provided for us.
NewModule->Buffer = &PCMCache->addBuffer(FileName, std::move(Buffer)); NewModule->Buffer = std::move(Buffer);
} else if (llvm::MemoryBuffer *Buffer = PCMCache->lookupBuffer(FileName)) {
NewModule->Buffer = Buffer;
} else { } else {
// Open the AST file. // Open the AST file.
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Buf((std::error_code())); llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Buf((std::error_code()));
@ -161,7 +158,7 @@ ModuleManager::addModule(StringRef FileName, ModuleKind Type,
return Missing; return Missing;
} }
NewModule->Buffer = &PCMCache->addBuffer(FileName, std::move(*Buf)); NewModule->Buffer = std::move(*Buf);
} }
// Initialize the stream. // Initialize the stream.
@ -170,13 +167,8 @@ ModuleManager::addModule(StringRef FileName, ModuleKind Type,
// Read the signature eagerly now so that we can check it. Avoid calling // Read the signature eagerly now so that we can check it. Avoid calling
// ReadSignature unless there's something to check though. // ReadSignature unless there's something to check though.
if (ExpectedSignature && checkSignature(ReadSignature(NewModule->Data), if (ExpectedSignature && checkSignature(ReadSignature(NewModule->Data),
ExpectedSignature, ErrorStr)) { ExpectedSignature, ErrorStr))
// Try to remove the buffer. If it can't be removed, then it was already
// validated by this process.
if (!PCMCache->tryToRemoveBuffer(NewModule->FileName))
FileMgr.invalidateCache(NewModule->File);
return OutOfDate; return OutOfDate;
}
// We're keeping this module. Store it everywhere. // We're keeping this module. Store it everywhere.
Module = Modules[Entry] = NewModule.get(); Module = Modules[Entry] = NewModule.get();
@ -243,12 +235,7 @@ void ModuleManager::removeModules(
// Files that didn't make it through ReadASTCore successfully will be // Files that didn't make it through ReadASTCore successfully will be
// rebuilt (or there was an error). Invalidate them so that we can load the // rebuilt (or there was an error). Invalidate them so that we can load the
// new files that will be renamed over the old ones. // new files that will be renamed over the old ones.
// if (LoadedSuccessfully.count(&*victim) == 0)
// The PCMCache tracks whether the module was succesfully loaded in another
// thread/context; in that case, it won't need to be rebuilt (and we can't
// safely invalidate it anyway).
if (LoadedSuccessfully.count(&*victim) == 0 &&
!PCMCache->tryToRemoveBuffer(victim->FileName))
FileMgr.invalidateCache(victim->File); FileMgr.invalidateCache(victim->File);
} }
@ -305,10 +292,10 @@ void ModuleManager::moduleFileAccepted(ModuleFile *MF) {
ModulesInCommonWithGlobalIndex.push_back(MF); ModulesInCommonWithGlobalIndex.push_back(MF);
} }
ModuleManager::ModuleManager(FileManager &FileMgr, MemoryBufferCache &PCMCache, ModuleManager::ModuleManager(FileManager &FileMgr,
const PCHContainerReader &PCHContainerRdr) const PCHContainerReader &PCHContainerRdr)
: FileMgr(FileMgr), PCMCache(&PCMCache), PCHContainerRdr(PCHContainerRdr), : FileMgr(FileMgr), PCHContainerRdr(PCHContainerRdr), GlobalIndex(),
GlobalIndex(), FirstVisitState(nullptr) {} FirstVisitState(nullptr) {}
ModuleManager::~ModuleManager() { delete FirstVisitState; } ModuleManager::~ModuleManager() { delete FirstVisitState; }

View File

@ -1 +0,0 @@
#import <Y.h>

View File

@ -1 +0,0 @@
//empty

View File

@ -1 +0,0 @@
#import <Y.h>

View File

@ -1,12 +0,0 @@
module X [system] {
header "X.h" // imports Y
export *
}
module Y {
header "Y.h"
export *
}
module Z {
header "Z.h" // imports Y
export *
}

View File

@ -1 +0,0 @@
struct Mismatch { int i; };

View File

@ -1,2 +0,0 @@
#import "Mismatch.h"
struct System { int i; };

View File

@ -1,7 +0,0 @@
module System [system] {
header "System.h"
}
module Mismatch {
header "Mismatch.h"
}

View File

@ -1,15 +0,0 @@
// RUN: rm -rf %t.cache
// RUN: echo "@import CoreText;" > %t.m
// RUN: %clang_cc1 -fdisable-module-hash -fmodules-cache-path=%t.cache \
// RUN: -fmodules -fimplicit-module-maps -I%S/Inputs/outofdate-rebuild %s \
// RUN: -fsyntax-only
// RUN: %clang_cc1 -DMISMATCH -Werror -fdisable-module-hash \
// RUN: -fmodules-cache-path=%t.cache -fmodules -fimplicit-module-maps \
// RUN: -I%S/Inputs/outofdate-rebuild %t.m -fsyntax-only
// RUN: %clang_cc1 -fdisable-module-hash -fmodules-cache-path=%t.cache \
// RUN: -fmodules -fimplicit-module-maps -I%S/Inputs/outofdate-rebuild %s \
// RUN: -fsyntax-only
// This testcase reproduces a use-after-free in when ModuleManager removes an
// entry from the PCMCache without notifying its parent ASTReader.
@import Cocoa;

View File

@ -1,17 +0,0 @@
// RUN: rm -rf %t.cache
// RUN: echo '@import X;' | \
// RUN: %clang_cc1 -fmodules -fimplicit-module-maps \
// RUN: -fmodules-cache-path=%t.cache -I%S/Inputs/system-out-of-date \
// RUN: -fsyntax-only -x objective-c -
//
// Build something with different diagnostic options.
// RUN: %clang_cc1 -fmodules -fimplicit-module-maps \
// RUN: -fmodules-cache-path=%t.cache -I%S/Inputs/system-out-of-date \
// RUN: -fsyntax-only %s -Wnon-modular-include-in-framework-module \
// RUN: -Werror=non-modular-include-in-framework-module 2>&1 \
// RUN: | FileCheck %s
@import X;
#import <Z.h>
// CHECK: While building module 'Z' imported from
// CHECK: {{.*}}Y-{{.*}}pcm' was validated as a system module and is now being imported as a non-system module

View File

@ -1,13 +0,0 @@
// RUN: rm -rf %t.cache
// RUN: echo "@import Mismatch;" >%t.m
// RUN: %clang_cc1 -Wno-system-headers -fdisable-module-hash \
// RUN: -fmodules-cache-path=%t.cache -fmodules -fimplicit-module-maps \
// RUN: -I%S/Inputs/warning-mismatch %t.m -fsyntax-only
// RUN: %clang_cc1 -Wsystem-headers -fdisable-module-hash \
// RUN: -fmodules-cache-path=%t.cache -fmodules -fimplicit-module-maps \
// RUN: -I%S/Inputs/warning-mismatch %s -fsyntax-only
// This testcase triggers a warning flag mismatch in an already validated
// header.
@import Mismatch;
@import System;

View File

@ -6,7 +6,6 @@ add_clang_unittest(BasicTests
CharInfoTest.cpp CharInfoTest.cpp
DiagnosticTest.cpp DiagnosticTest.cpp
FileManagerTest.cpp FileManagerTest.cpp
MemoryBufferCacheTest.cpp
SourceManagerTest.cpp SourceManagerTest.cpp
VirtualFileSystemTest.cpp VirtualFileSystemTest.cpp
) )

View File

@ -1,94 +0,0 @@
//===- MemoryBufferCacheTest.cpp - MemoryBufferCache tests ----------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "clang/Basic/MemoryBufferCache.h"
#include "llvm/Support/MemoryBuffer.h"
#include "gtest/gtest.h"
using namespace llvm;
using namespace clang;
namespace {
std::unique_ptr<MemoryBuffer> getBuffer(int I) {
SmallVector<char, 8> Bytes;
raw_svector_ostream(Bytes) << "data:" << I;
return MemoryBuffer::getMemBuffer(StringRef(Bytes.data(), Bytes.size()));
}
TEST(MemoryBufferCacheTest, addBuffer) {
auto B1 = getBuffer(1);
auto B2 = getBuffer(2);
auto B3 = getBuffer(3);
auto *RawB1 = B1.get();
auto *RawB2 = B2.get();
auto *RawB3 = B3.get();
// Add a few buffers.
MemoryBufferCache Cache;
EXPECT_EQ(RawB1, &Cache.addBuffer("1", std::move(B1)));
EXPECT_EQ(RawB2, &Cache.addBuffer("2", std::move(B2)));
EXPECT_EQ(RawB3, &Cache.addBuffer("3", std::move(B3)));
EXPECT_EQ(RawB1, Cache.lookupBuffer("1"));
EXPECT_EQ(RawB2, Cache.lookupBuffer("2"));
EXPECT_EQ(RawB3, Cache.lookupBuffer("3"));
EXPECT_FALSE(Cache.isBufferFinal("1"));
EXPECT_FALSE(Cache.isBufferFinal("2"));
EXPECT_FALSE(Cache.isBufferFinal("3"));
// Remove the middle buffer.
EXPECT_FALSE(Cache.tryToRemoveBuffer("2"));
EXPECT_EQ(nullptr, Cache.lookupBuffer("2"));
EXPECT_FALSE(Cache.isBufferFinal("2"));
// Replace the middle buffer.
B2 = getBuffer(2);
ASSERT_NE(RawB2, B2.get());
RawB2 = B2.get();
EXPECT_EQ(RawB2, &Cache.addBuffer("2", std::move(B2)));
// Check that nothing is final.
EXPECT_FALSE(Cache.isBufferFinal("1"));
EXPECT_FALSE(Cache.isBufferFinal("2"));
EXPECT_FALSE(Cache.isBufferFinal("3"));
}
TEST(MemoryBufferCacheTest, finalizeCurrentBuffers) {
// Add a buffer.
MemoryBufferCache Cache;
auto B1 = getBuffer(1);
auto *RawB1 = B1.get();
Cache.addBuffer("1", std::move(B1));
ASSERT_FALSE(Cache.isBufferFinal("1"));
// Finalize it.
Cache.finalizeCurrentBuffers();
EXPECT_TRUE(Cache.isBufferFinal("1"));
EXPECT_TRUE(Cache.tryToRemoveBuffer("1"));
EXPECT_EQ(RawB1, Cache.lookupBuffer("1"));
EXPECT_TRUE(Cache.isBufferFinal("1"));
// Repeat.
auto B2 = getBuffer(2);
auto *RawB2 = B2.get();
Cache.addBuffer("2", std::move(B2));
EXPECT_FALSE(Cache.isBufferFinal("2"));
Cache.finalizeCurrentBuffers();
EXPECT_TRUE(Cache.isBufferFinal("1"));
EXPECT_TRUE(Cache.isBufferFinal("2"));
EXPECT_TRUE(Cache.tryToRemoveBuffer("1"));
EXPECT_TRUE(Cache.tryToRemoveBuffer("2"));
EXPECT_EQ(RawB1, Cache.lookupBuffer("1"));
EXPECT_EQ(RawB2, Cache.lookupBuffer("2"));
EXPECT_TRUE(Cache.isBufferFinal("1"));
EXPECT_TRUE(Cache.isBufferFinal("2"));
}
} // namespace

View File

@ -12,7 +12,6 @@
#include "clang/Basic/DiagnosticOptions.h" #include "clang/Basic/DiagnosticOptions.h"
#include "clang/Basic/FileManager.h" #include "clang/Basic/FileManager.h"
#include "clang/Basic/LangOptions.h" #include "clang/Basic/LangOptions.h"
#include "clang/Basic/MemoryBufferCache.h"
#include "clang/Basic/TargetInfo.h" #include "clang/Basic/TargetInfo.h"
#include "clang/Basic/TargetOptions.h" #include "clang/Basic/TargetOptions.h"
#include "clang/Lex/HeaderSearch.h" #include "clang/Lex/HeaderSearch.h"
@ -79,11 +78,10 @@ TEST_F(SourceManagerTest, isBeforeInTranslationUnit) {
SourceMgr.setMainFileID(mainFileID); SourceMgr.setMainFileID(mainFileID);
VoidModuleLoader ModLoader; VoidModuleLoader ModLoader;
MemoryBufferCache PCMCache;
HeaderSearch HeaderInfo(std::make_shared<HeaderSearchOptions>(), SourceMgr, HeaderSearch HeaderInfo(std::make_shared<HeaderSearchOptions>(), SourceMgr,
Diags, LangOpts, &*Target); Diags, LangOpts, &*Target);
Preprocessor PP(std::make_shared<PreprocessorOptions>(), Diags, LangOpts, Preprocessor PP(std::make_shared<PreprocessorOptions>(), Diags, LangOpts,
SourceMgr, PCMCache, HeaderInfo, ModLoader, SourceMgr, HeaderInfo, ModLoader,
/*IILookup =*/nullptr, /*IILookup =*/nullptr,
/*OwnsHeaderSearch =*/false); /*OwnsHeaderSearch =*/false);
PP.Initialize(*Target); PP.Initialize(*Target);
@ -200,11 +198,10 @@ TEST_F(SourceManagerTest, getMacroArgExpandedLocation) {
SourceMgr.overrideFileContents(headerFile, std::move(HeaderBuf)); SourceMgr.overrideFileContents(headerFile, std::move(HeaderBuf));
VoidModuleLoader ModLoader; VoidModuleLoader ModLoader;
MemoryBufferCache PCMCache;
HeaderSearch HeaderInfo(std::make_shared<HeaderSearchOptions>(), SourceMgr, HeaderSearch HeaderInfo(std::make_shared<HeaderSearchOptions>(), SourceMgr,
Diags, LangOpts, &*Target); Diags, LangOpts, &*Target);
Preprocessor PP(std::make_shared<PreprocessorOptions>(), Diags, LangOpts, Preprocessor PP(std::make_shared<PreprocessorOptions>(), Diags, LangOpts,
SourceMgr, PCMCache, HeaderInfo, ModLoader, SourceMgr, HeaderInfo, ModLoader,
/*IILookup =*/nullptr, /*IILookup =*/nullptr,
/*OwnsHeaderSearch =*/false); /*OwnsHeaderSearch =*/false);
PP.Initialize(*Target); PP.Initialize(*Target);
@ -301,11 +298,10 @@ TEST_F(SourceManagerTest, isBeforeInTranslationUnitWithMacroInInclude) {
SourceMgr.overrideFileContents(headerFile, std::move(HeaderBuf)); SourceMgr.overrideFileContents(headerFile, std::move(HeaderBuf));
VoidModuleLoader ModLoader; VoidModuleLoader ModLoader;
MemoryBufferCache PCMCache;
HeaderSearch HeaderInfo(std::make_shared<HeaderSearchOptions>(), SourceMgr, HeaderSearch HeaderInfo(std::make_shared<HeaderSearchOptions>(), SourceMgr,
Diags, LangOpts, &*Target); Diags, LangOpts, &*Target);
Preprocessor PP(std::make_shared<PreprocessorOptions>(), Diags, LangOpts, Preprocessor PP(std::make_shared<PreprocessorOptions>(), Diags, LangOpts,
SourceMgr, PCMCache, HeaderInfo, ModLoader, SourceMgr, HeaderInfo, ModLoader,
/*IILookup =*/nullptr, /*IILookup =*/nullptr,
/*OwnsHeaderSearch =*/false); /*OwnsHeaderSearch =*/false);
PP.Initialize(*Target); PP.Initialize(*Target);

View File

@ -12,7 +12,6 @@
#include "clang/Basic/DiagnosticOptions.h" #include "clang/Basic/DiagnosticOptions.h"
#include "clang/Basic/FileManager.h" #include "clang/Basic/FileManager.h"
#include "clang/Basic/LangOptions.h" #include "clang/Basic/LangOptions.h"
#include "clang/Basic/MemoryBufferCache.h"
#include "clang/Basic/SourceManager.h" #include "clang/Basic/SourceManager.h"
#include "clang/Basic/TargetInfo.h" #include "clang/Basic/TargetInfo.h"
#include "clang/Basic/TargetOptions.h" #include "clang/Basic/TargetOptions.h"
@ -65,12 +64,10 @@ protected:
SourceMgr.setMainFileID(SourceMgr.createFileID(std::move(Buf))); SourceMgr.setMainFileID(SourceMgr.createFileID(std::move(Buf)));
VoidModuleLoader ModLoader; VoidModuleLoader ModLoader;
MemoryBufferCache PCMCache;
HeaderSearch HeaderInfo(std::make_shared<HeaderSearchOptions>(), SourceMgr, HeaderSearch HeaderInfo(std::make_shared<HeaderSearchOptions>(), SourceMgr,
Diags, LangOpts, Target.get()); Diags, LangOpts, Target.get());
Preprocessor PP(std::make_shared<PreprocessorOptions>(), Diags, LangOpts, Preprocessor PP(std::make_shared<PreprocessorOptions>(), Diags, LangOpts,
SourceMgr, PCMCache, HeaderInfo, ModLoader, SourceMgr, HeaderInfo, ModLoader, /*IILookup =*/nullptr,
/*IILookup =*/nullptr,
/*OwnsHeaderSearch =*/false); /*OwnsHeaderSearch =*/false);
PP.Initialize(*Target); PP.Initialize(*Target);
PP.EnterMainSourceFile(); PP.EnterMainSourceFile();

View File

@ -14,7 +14,6 @@
#include "clang/Basic/DiagnosticOptions.h" #include "clang/Basic/DiagnosticOptions.h"
#include "clang/Basic/FileManager.h" #include "clang/Basic/FileManager.h"
#include "clang/Basic/LangOptions.h" #include "clang/Basic/LangOptions.h"
#include "clang/Basic/MemoryBufferCache.h"
#include "clang/Basic/SourceManager.h" #include "clang/Basic/SourceManager.h"
#include "clang/Basic/TargetInfo.h" #include "clang/Basic/TargetInfo.h"
#include "clang/Basic/TargetOptions.h" #include "clang/Basic/TargetOptions.h"
@ -162,14 +161,13 @@ protected:
SourceMgr.setMainFileID(SourceMgr.createFileID(std::move(Buf))); SourceMgr.setMainFileID(SourceMgr.createFileID(std::move(Buf)));
VoidModuleLoader ModLoader; VoidModuleLoader ModLoader;
MemoryBufferCache PCMCache;
HeaderSearch HeaderInfo(std::make_shared<HeaderSearchOptions>(), SourceMgr, HeaderSearch HeaderInfo(std::make_shared<HeaderSearchOptions>(), SourceMgr,
Diags, LangOpts, Target.get()); Diags, LangOpts, Target.get());
AddFakeHeader(HeaderInfo, HeaderPath, SystemHeader); AddFakeHeader(HeaderInfo, HeaderPath, SystemHeader);
Preprocessor PP(std::make_shared<PreprocessorOptions>(), Diags, LangOpts, Preprocessor PP(std::make_shared<PreprocessorOptions>(), Diags, LangOpts,
SourceMgr, PCMCache, HeaderInfo, ModLoader, SourceMgr, HeaderInfo, ModLoader,
/*IILookup =*/nullptr, /*IILookup =*/nullptr,
/*OwnsHeaderSearch =*/false); /*OwnsHeaderSearch =*/false);
PP.Initialize(*Target); PP.Initialize(*Target);
@ -200,12 +198,11 @@ protected:
SourceMgr.setMainFileID(SourceMgr.createFileID(std::move(SourceBuf))); SourceMgr.setMainFileID(SourceMgr.createFileID(std::move(SourceBuf)));
VoidModuleLoader ModLoader; VoidModuleLoader ModLoader;
MemoryBufferCache PCMCache;
HeaderSearch HeaderInfo(std::make_shared<HeaderSearchOptions>(), SourceMgr, HeaderSearch HeaderInfo(std::make_shared<HeaderSearchOptions>(), SourceMgr,
Diags, OpenCLLangOpts, Target.get()); Diags, OpenCLLangOpts, Target.get());
Preprocessor PP(std::make_shared<PreprocessorOptions>(), Diags, Preprocessor PP(std::make_shared<PreprocessorOptions>(), Diags,
OpenCLLangOpts, SourceMgr, PCMCache, HeaderInfo, ModLoader, OpenCLLangOpts, SourceMgr, HeaderInfo, ModLoader,
/*IILookup =*/nullptr, /*IILookup =*/nullptr,
/*OwnsHeaderSearch =*/false); /*OwnsHeaderSearch =*/false);
PP.Initialize(*Target); PP.Initialize(*Target);

View File

@ -12,7 +12,6 @@
#include "clang/Basic/DiagnosticOptions.h" #include "clang/Basic/DiagnosticOptions.h"
#include "clang/Basic/FileManager.h" #include "clang/Basic/FileManager.h"
#include "clang/Basic/LangOptions.h" #include "clang/Basic/LangOptions.h"
#include "clang/Basic/MemoryBufferCache.h"
#include "clang/Basic/SourceManager.h" #include "clang/Basic/SourceManager.h"
#include "clang/Basic/TargetInfo.h" #include "clang/Basic/TargetInfo.h"
#include "clang/Basic/TargetOptions.h" #include "clang/Basic/TargetOptions.h"
@ -94,11 +93,10 @@ TEST_F(PPConditionalDirectiveRecordTest, PPRecAPI) {
SourceMgr.setMainFileID(SourceMgr.createFileID(std::move(Buf))); SourceMgr.setMainFileID(SourceMgr.createFileID(std::move(Buf)));
VoidModuleLoader ModLoader; VoidModuleLoader ModLoader;
MemoryBufferCache PCMCache;
HeaderSearch HeaderInfo(std::make_shared<HeaderSearchOptions>(), SourceMgr, HeaderSearch HeaderInfo(std::make_shared<HeaderSearchOptions>(), SourceMgr,
Diags, LangOpts, Target.get()); Diags, LangOpts, Target.get());
Preprocessor PP(std::make_shared<PreprocessorOptions>(), Diags, LangOpts, Preprocessor PP(std::make_shared<PreprocessorOptions>(), Diags, LangOpts,
SourceMgr, PCMCache, HeaderInfo, ModLoader, SourceMgr, HeaderInfo, ModLoader,
/*IILookup =*/nullptr, /*IILookup =*/nullptr,
/*OwnsHeaderSearch =*/false); /*OwnsHeaderSearch =*/false);
PP.Initialize(*Target); PP.Initialize(*Target);