From d7c16b254332796d6ce111b50ce2cf6fbfce8e7a Mon Sep 17 00:00:00 2001 From: Argyrios Kyrtzidis Date: Wed, 31 Oct 2012 20:59:50 +0000 Subject: [PATCH] [PCH] Remove the stat cache from the PCH file. The stat cache became essentially useless ever since we started validating all file entries in the PCH. But the motivating reason for removing it now is that it also affected correctness in this situation: -You have a header without include guards (using "#pragma once" or #import) -When creating the PCH: -The same header is referenced in an #include with different filename cases. -In the PCH, of course, we record only one file entry for the header file -But we cache in the PCH file the stat info for both filename cases -Then the source files are updated and the header file is updated in a way that its size and modification time are the same but its inode changes -When using the PCH: -We validate the headers, we check that header file and we create a file entry with its current inode -There's another #include with a filename with different case than the previously created file entry -In order to get its stat info we go through the cached stat info of the PCH and we receive the old inode -because of the different inodes, we think they are different files so we go ahead and include its contents. Removing the stat cache will potentially break clients that are attempting to use the stat cache as a way of avoiding having the actual input files available. If that use case is important, patches are welcome to bring it back in a way that will actually work correctly (i.e., emit a PCH that is self-contained, coping with literal strings, line/column computations, etc.). This fixes rdar://5502805 llvm-svn: 167172 --- clang/include/clang/Frontend/CompilerInstance.h | 2 - clang/include/clang/Lex/PreprocessorOptions.h | 6 +- clang/include/clang/Serialization/ASTBitCodes.h | 3 - clang/include/clang/Serialization/ASTReader.h | 15 +-- clang/include/clang/Serialization/ASTWriter.h | 10 +- clang/include/clang/Serialization/Module.h | 5 - clang/lib/Frontend/ASTUnit.cpp | 5 +- clang/lib/Frontend/CompilerInstance.cpp | 8 +- clang/lib/Frontend/FrontendAction.cpp | 1 - clang/lib/Serialization/ASTReader.cpp | 116 +---------------------- clang/lib/Serialization/ASTWriter.cpp | 49 +--------- clang/lib/Serialization/GeneratePCH.cpp | 9 +- clang/lib/Serialization/Module.cpp | 2 +- clang/test/PCH/Inputs/case-insensitive-include.h | 5 + clang/test/PCH/case-insensitive-include.c | 29 ++++++ clang/test/lit.cfg | 12 +++ 16 files changed, 60 insertions(+), 217 deletions(-) create mode 100644 clang/test/PCH/Inputs/case-insensitive-include.h create mode 100644 clang/test/PCH/case-insensitive-include.c diff --git a/clang/include/clang/Frontend/CompilerInstance.h b/clang/include/clang/Frontend/CompilerInstance.h index 548ff86..3173ad4 100644 --- a/clang/include/clang/Frontend/CompilerInstance.h +++ b/clang/include/clang/Frontend/CompilerInstance.h @@ -531,7 +531,6 @@ public: /// context. void createPCHExternalASTSource(StringRef Path, bool DisablePCHValidation, - bool DisableStatCache, bool AllowPCHWithCompilerErrors, void *DeserializationListener); @@ -541,7 +540,6 @@ public: static ExternalASTSource * createPCHExternalASTSource(StringRef Path, const std::string &Sysroot, bool DisablePCHValidation, - bool DisableStatCache, bool AllowPCHWithCompilerErrors, Preprocessor &PP, ASTContext &Context, void *DeserializationListener, bool Preamble); diff --git a/clang/include/clang/Lex/PreprocessorOptions.h b/clang/include/clang/Lex/PreprocessorOptions.h index 4f32360..e5fe373 100644 --- a/clang/include/clang/Lex/PreprocessorOptions.h +++ b/clang/include/clang/Lex/PreprocessorOptions.h @@ -66,10 +66,6 @@ public: /// precompiled headers. bool DisablePCHValidation; - /// \brief When true, disables the use of the stat cache within a - /// precompiled header or AST file. - bool DisableStatCache; - /// \brief When true, a PCH with compiler errors will not be rejected. bool AllowPCHWithCompilerErrors; @@ -168,7 +164,7 @@ public: public: PreprocessorOptions() : UsePredefines(true), DetailedRecord(false), DetailedRecordConditionalDirectives(false), - DisablePCHValidation(false), DisableStatCache(false), + DisablePCHValidation(false), AllowPCHWithCompilerErrors(false), DumpDeserializedPCHDecls(false), PrecompiledPreambleBytes(0, true), diff --git a/clang/include/clang/Serialization/ASTBitCodes.h b/clang/include/clang/Serialization/ASTBitCodes.h index 4dba7b5..8c58fb2 100644 --- a/clang/include/clang/Serialization/ASTBitCodes.h +++ b/clang/include/clang/Serialization/ASTBitCodes.h @@ -386,9 +386,6 @@ namespace clang { /// preloaded. SOURCE_LOCATION_PRELOADS = 14, - /// \brief Record code for the stat() cache. - STAT_CACHE = 15, - /// \brief Record code for the set of ext_vector type names. EXT_VECTOR_DECLS = 16, diff --git a/clang/include/clang/Serialization/ASTReader.h b/clang/include/clang/Serialization/ASTReader.h index c0d93c3..ba26a49 100644 --- a/clang/include/clang/Serialization/ASTReader.h +++ b/clang/include/clang/Serialization/ASTReader.h @@ -690,9 +690,6 @@ private: /// headers when they are loaded. bool DisableValidation; - /// \brief Whether to disable the use of stat caches in AST files. - bool DisableStatCache; - /// \brief Whether to accept an AST file with compiler errors. bool AllowASTWithCompilerErrors; @@ -709,10 +706,6 @@ private: SwitchCaseMapTy *CurrSwitchCaseStmts; - /// \brief The number of stat() calls that hit/missed the stat - /// cache. - unsigned NumStatHits, NumStatMisses; - /// \brief The number of source location entries de-serialized from /// the PCH file. unsigned NumSLocEntriesRead; @@ -1069,17 +1062,11 @@ public: /// of its regular consistency checking, allowing the use of precompiled /// headers that cannot be determined to be compatible. /// - /// \param DisableStatCache If true, the AST reader will ignore the - /// stat cache in the AST files. This performance pessimization can - /// help when an AST file is being used in cases where the - /// underlying files in the file system may have changed, but - /// parsing should still continue. - /// /// \param AllowASTWithCompilerErrors If true, the AST reader will accept an /// AST file the was created out of an AST with compiler errors, /// otherwise it will reject it. ASTReader(Preprocessor &PP, ASTContext &Context, StringRef isysroot = "", - bool DisableValidation = false, bool DisableStatCache = false, + bool DisableValidation = false, bool AllowASTWithCompilerErrors = false); ~ASTReader(); diff --git a/clang/include/clang/Serialization/ASTWriter.h b/clang/include/clang/Serialization/ASTWriter.h index 919209c..ac81e21 100644 --- a/clang/include/clang/Serialization/ASTWriter.h +++ b/clang/include/clang/Serialization/ASTWriter.h @@ -50,7 +50,6 @@ class FPOptions; class HeaderSearch; class IdentifierResolver; class MacroDefinition; -class MemorizeStatCalls; class OpaqueValueExpr; class OpenCLOptions; class ASTReader; @@ -417,7 +416,6 @@ private: void WriteControlBlock(Preprocessor &PP, ASTContext &Context, StringRef isysroot, const std::string &OutputFile); void WriteInputFiles(SourceManager &SourceMgr, StringRef isysroot); - void WriteStatCache(MemorizeStatCalls &StatCalls); void WriteSourceManagerBlock(SourceManager &SourceMgr, const Preprocessor &PP, StringRef isysroot); @@ -467,7 +465,7 @@ private: void WriteDeclsBlockAbbrevs(); void WriteDecl(ASTContext &Context, Decl *D); - void WriteASTCore(Sema &SemaRef, MemorizeStatCalls *StatCalls, + void WriteASTCore(Sema &SemaRef, StringRef isysroot, const std::string &OutputFile, Module *WritingModule); @@ -482,15 +480,12 @@ public: /// \param SemaRef a reference to the semantic analysis object that processed /// the AST to be written into the precompiled header. /// - /// \param StatCalls the object that cached all of the stat() calls made while - /// searching for source files and headers. - /// /// \param WritingModule The module that we are writing. If null, we are /// writing a precompiled header. /// /// \param isysroot if non-empty, write a relocatable file whose headers /// are relative to the given system root. - void WriteAST(Sema &SemaRef, MemorizeStatCalls *StatCalls, + void WriteAST(Sema &SemaRef, const std::string &OutputFile, Module *WritingModule, StringRef isysroot, bool hasErrors = false); @@ -733,7 +728,6 @@ class PCHGenerator : public SemaConsumer { std::string isysroot; raw_ostream *Out; Sema *SemaPtr; - MemorizeStatCalls *StatCalls; // owned by the FileManager llvm::SmallVector Buffer; llvm::BitstreamWriter Stream; ASTWriter Writer; diff --git a/clang/include/clang/Serialization/Module.h b/clang/include/clang/Serialization/Module.h index 2915cfc..39fa3d9 100644 --- a/clang/include/clang/Serialization/Module.h +++ b/clang/include/clang/Serialization/Module.h @@ -385,11 +385,6 @@ public: /// \brief Diagnostic IDs and their mappings that the user changed. SmallVector PragmaDiagMappings; - /// \brief The AST stat cache installed for this file, if any. - /// - /// The dynamic type of this stat cache is always ASTStatCache - void *StatCache; - /// \brief List of modules which depend on this module llvm::SetVector ImportedBy; diff --git a/clang/lib/Frontend/ASTUnit.cpp b/clang/lib/Frontend/ASTUnit.cpp index cc93d46..da30832 100644 --- a/clang/lib/Frontend/ASTUnit.cpp +++ b/clang/lib/Frontend/ASTUnit.cpp @@ -779,7 +779,6 @@ ASTUnit *ASTUnit::LoadFromASTFile(const std::string &Filename, Reader.reset(new ASTReader(PP, Context, /*isysroot=*/"", /*DisableValidation=*/disableValid, - /*DisableStatCache=*/false, AllowPCHWithCompilerErrors)); // Recover resources if we crash before exiting this method. @@ -2023,7 +2022,6 @@ bool ASTUnit::Reparse(RemappedFile *RemappedFiles, unsigned NumRemappedFiles) { // Remap files. PreprocessorOptions &PPOpts = Invocation->getPreprocessorOpts(); - PPOpts.DisableStatCache = true; for (PreprocessorOptions::remapped_file_buffer_iterator R = PPOpts.remapped_file_buffer_begin(), REnd = PPOpts.remapped_file_buffer_end(); @@ -2436,7 +2434,6 @@ void ASTUnit::CodeComplete(StringRef File, unsigned Line, unsigned Column, // If the main file has been overridden due to the use of a preamble, // make that override happen and introduce the preamble. - PreprocessorOpts.DisableStatCache = true; StoredDiagnostics.insert(StoredDiagnostics.end(), stored_diag_begin(), stored_diag_afterDriver_begin()); @@ -2509,7 +2506,7 @@ static bool serializeUnit(ASTWriter &Writer, Sema &S, bool hasErrors, raw_ostream &OS) { - Writer.WriteAST(S, 0, std::string(), 0, "", hasErrors); + Writer.WriteAST(S, std::string(), 0, "", hasErrors); // Write the generated bitstream to "Out". if (!Buffer.empty()) diff --git a/clang/lib/Frontend/CompilerInstance.cpp b/clang/lib/Frontend/CompilerInstance.cpp index 80d15c6..c6c5fb5 100644 --- a/clang/lib/Frontend/CompilerInstance.cpp +++ b/clang/lib/Frontend/CompilerInstance.cpp @@ -308,14 +308,12 @@ void CompilerInstance::createASTContext() { void CompilerInstance::createPCHExternalASTSource(StringRef Path, bool DisablePCHValidation, - bool DisableStatCache, bool AllowPCHWithCompilerErrors, void *DeserializationListener){ OwningPtr Source; bool Preamble = getPreprocessorOpts().PrecompiledPreambleBytes.first != 0; Source.reset(createPCHExternalASTSource(Path, getHeaderSearchOpts().Sysroot, DisablePCHValidation, - DisableStatCache, AllowPCHWithCompilerErrors, getPreprocessor(), getASTContext(), DeserializationListener, @@ -328,7 +326,6 @@ ExternalASTSource * CompilerInstance::createPCHExternalASTSource(StringRef Path, const std::string &Sysroot, bool DisablePCHValidation, - bool DisableStatCache, bool AllowPCHWithCompilerErrors, Preprocessor &PP, ASTContext &Context, @@ -337,7 +334,7 @@ CompilerInstance::createPCHExternalASTSource(StringRef Path, OwningPtr Reader; Reader.reset(new ASTReader(PP, Context, Sysroot.empty() ? "" : Sysroot.c_str(), - DisablePCHValidation, DisableStatCache, + DisablePCHValidation, AllowPCHWithCompilerErrors)); Reader->setDeserializationListener( @@ -946,8 +943,7 @@ Module *CompilerInstance::loadModule(SourceLocation ImportLoc, const PreprocessorOptions &PPOpts = getPreprocessorOpts(); ModuleManager = new ASTReader(getPreprocessor(), *Context, Sysroot.empty() ? "" : Sysroot.c_str(), - PPOpts.DisablePCHValidation, - PPOpts.DisableStatCache); + PPOpts.DisablePCHValidation); if (hasASTConsumer()) { ModuleManager->setDeserializationListener( getASTConsumer().GetASTDeserializationListener()); diff --git a/clang/lib/Frontend/FrontendAction.cpp b/clang/lib/Frontend/FrontendAction.cpp index fa1655d..2974334 100644 --- a/clang/lib/Frontend/FrontendAction.cpp +++ b/clang/lib/Frontend/FrontendAction.cpp @@ -314,7 +314,6 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI, CI.createPCHExternalASTSource( CI.getPreprocessorOpts().ImplicitPCHInclude, CI.getPreprocessorOpts().DisablePCHValidation, - CI.getPreprocessorOpts().DisableStatCache, CI.getPreprocessorOpts().AllowPCHWithCompilerErrors, DeserialListener); if (!CI.getASTContext().getExternalSource()) diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index 874d2c4..80fb464 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -769,104 +769,6 @@ bool ASTReader::ParseLineTable(ModuleFile &F, return false; } -namespace { - -class ASTStatData { -public: - const ino_t ino; - const dev_t dev; - const mode_t mode; - const time_t mtime; - const off_t size; - - ASTStatData(ino_t i, dev_t d, mode_t mo, time_t m, off_t s) - : ino(i), dev(d), mode(mo), mtime(m), size(s) {} -}; - -class ASTStatLookupTrait { - public: - typedef const char *external_key_type; - typedef const char *internal_key_type; - - typedef ASTStatData data_type; - - static unsigned ComputeHash(const char *path) { - return llvm::HashString(path); - } - - static internal_key_type GetInternalKey(const char *path) { return path; } - - static bool EqualKey(internal_key_type a, internal_key_type b) { - return strcmp(a, b) == 0; - } - - static std::pair - ReadKeyDataLength(const unsigned char*& d) { - unsigned KeyLen = (unsigned) clang::io::ReadUnalignedLE16(d); - unsigned DataLen = (unsigned) *d++; - return std::make_pair(KeyLen + 1, DataLen); - } - - static internal_key_type ReadKey(const unsigned char *d, unsigned) { - return (const char *)d; - } - - static data_type ReadData(const internal_key_type, const unsigned char *d, - unsigned /*DataLen*/) { - using namespace clang::io; - - ino_t ino = (ino_t) ReadUnalignedLE32(d); - dev_t dev = (dev_t) ReadUnalignedLE32(d); - mode_t mode = (mode_t) ReadUnalignedLE16(d); - time_t mtime = (time_t) ReadUnalignedLE64(d); - off_t size = (off_t) ReadUnalignedLE64(d); - return data_type(ino, dev, mode, mtime, size); - } -}; - -/// \brief stat() cache for precompiled headers. -/// -/// This cache is very similar to the stat cache used by pretokenized -/// headers. -class ASTStatCache : public FileSystemStatCache { - typedef OnDiskChainedHashTable CacheTy; - CacheTy *Cache; - - unsigned &NumStatHits, &NumStatMisses; -public: - ASTStatCache(const unsigned char *Buckets, const unsigned char *Base, - unsigned &NumStatHits, unsigned &NumStatMisses) - : Cache(0), NumStatHits(NumStatHits), NumStatMisses(NumStatMisses) { - Cache = CacheTy::Create(Buckets, Base); - } - - ~ASTStatCache() { delete Cache; } - - LookupResult getStat(const char *Path, struct stat &StatBuf, - int *FileDescriptor) { - // Do the lookup for the file's data in the AST file. - CacheTy::iterator I = Cache->find(Path); - - // If we don't get a hit in the AST file just forward to 'stat'. - if (I == Cache->end()) { - ++NumStatMisses; - return statChained(Path, StatBuf, FileDescriptor); - } - - ++NumStatHits; - ASTStatData Data = *I; - - StatBuf.st_ino = Data.ino; - StatBuf.st_dev = Data.dev; - StatBuf.st_mtime = Data.mtime; - StatBuf.st_mode = Data.mode; - StatBuf.st_size = Data.size; - return CacheExists; - } -}; -} // end anonymous namespace - - /// \brief Read a source manager block bool ASTReader::ReadSourceManagerBlock(ModuleFile &F) { using namespace SrcMgr; @@ -2362,18 +2264,6 @@ bool ASTReader::ReadASTBlock(ModuleFile &F) { break; } - case STAT_CACHE: { - if (!DisableStatCache) { - ASTStatCache *MyStatCache = - new ASTStatCache((const unsigned char *)BlobStart + Record[0], - (const unsigned char *)BlobStart, - NumStatHits, NumStatMisses); - FileMgr.addStatCache(MyStatCache); - F.StatCache = MyStatCache; - } - break; - } - case EXT_VECTOR_DECLS: for (unsigned I = 0, N = Record.size(); I != N; ++I) ExtVectorDecls.push_back(getGlobalDeclID(F, Record[I])); @@ -5624,8 +5514,6 @@ void ASTReader::PrintStats() { SelectorsLoaded.end(), Selector()); - std::fprintf(stderr, " %u stat cache hits\n", NumStatHits); - std::fprintf(stderr, " %u stat cache misses\n", NumStatMisses); if (unsigned TotalNumSLocEntries = getTotalNumSLocs()) std::fprintf(stderr, " %u/%u source location entries read (%f%%)\n", NumSLocEntriesRead, TotalNumSLocEntries, @@ -7005,16 +6893,14 @@ void ASTReader::FinishedDeserializing() { ASTReader::ASTReader(Preprocessor &PP, ASTContext &Context, StringRef isysroot, bool DisableValidation, - bool DisableStatCache, bool AllowASTWithCompilerErrors) + bool AllowASTWithCompilerErrors) : Listener(new PCHValidator(PP, *this)), DeserializationListener(0), SourceMgr(PP.getSourceManager()), FileMgr(PP.getFileManager()), Diags(PP.getDiagnostics()), SemaObj(0), PP(PP), Context(Context), Consumer(0), ModuleMgr(PP.getFileManager()), isysroot(isysroot), DisableValidation(DisableValidation), - DisableStatCache(DisableStatCache), AllowASTWithCompilerErrors(AllowASTWithCompilerErrors), CurrentGeneration(0), CurrSwitchCaseStmts(&SwitchCaseStmts), - NumStatHits(0), NumStatMisses(0), NumSLocEntriesRead(0), TotalNumSLocEntries(0), NumStatementsRead(0), TotalNumStatements(0), NumMacrosRead(0), TotalNumMacros(0), NumSelectorsRead(0), NumMethodPoolEntriesRead(0), diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index 500351f..a2e8b71 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -803,7 +803,6 @@ void ASTWriter::WriteBlockInfoBlock() { RECORD(PP_COUNTER_VALUE); RECORD(SOURCE_LOCATION_OFFSETS); RECORD(SOURCE_LOCATION_PRELOADS); - RECORD(STAT_CACHE); RECORD(EXT_VECTOR_DECLS); RECORD(PPD_ENTITIES_OFFSETS); RECORD(REFERENCED_SELECTOR_POOL); @@ -1328,46 +1327,6 @@ public: }; } // end anonymous namespace -/// \brief Write the stat() system call cache to the AST file. -void ASTWriter::WriteStatCache(MemorizeStatCalls &StatCalls) { - // Build the on-disk hash table containing information about every - // stat() call. - OnDiskChainedHashTableGenerator Generator; - unsigned NumStatEntries = 0; - for (MemorizeStatCalls::iterator Stat = StatCalls.begin(), - StatEnd = StatCalls.end(); - Stat != StatEnd; ++Stat, ++NumStatEntries) { - StringRef Filename = Stat->first(); - Generator.insert(Filename.data(), Stat->second); - } - - // Create the on-disk hash table in a buffer. - SmallString<4096> StatCacheData; - uint32_t BucketOffset; - { - llvm::raw_svector_ostream Out(StatCacheData); - // Make sure that no bucket is at offset 0 - clang::io::Emit32(Out, 0); - BucketOffset = Generator.Emit(Out); - } - - // Create a blob abbreviation - using namespace llvm; - BitCodeAbbrev *Abbrev = new BitCodeAbbrev(); - Abbrev->Add(BitCodeAbbrevOp(STAT_CACHE)); - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); - unsigned StatCacheAbbrev = Stream.EmitAbbrev(Abbrev); - - // Write the stat cache - RecordData Record; - Record.push_back(STAT_CACHE); - Record.push_back(BucketOffset); - Record.push_back(NumStatEntries); - Stream.EmitRecordWithBlob(StatCacheAbbrev, Record, StatCacheData.str()); -} - //===----------------------------------------------------------------------===// // Source Manager Serialization //===----------------------------------------------------------------------===// @@ -3404,7 +3363,7 @@ ASTWriter::~ASTWriter() { delete I->second; } -void ASTWriter::WriteAST(Sema &SemaRef, MemorizeStatCalls *StatCalls, +void ASTWriter::WriteAST(Sema &SemaRef, const std::string &OutputFile, Module *WritingModule, StringRef isysroot, bool hasErrors) { @@ -3423,7 +3382,7 @@ void ASTWriter::WriteAST(Sema &SemaRef, MemorizeStatCalls *StatCalls, Context = &SemaRef.Context; PP = &SemaRef.PP; this->WritingModule = WritingModule; - WriteASTCore(SemaRef, StatCalls, isysroot, OutputFile, WritingModule); + WriteASTCore(SemaRef, isysroot, OutputFile, WritingModule); Context = 0; PP = 0; this->WritingModule = 0; @@ -3440,7 +3399,7 @@ static void AddLazyVectorDecls(ASTWriter &Writer, Vector &Vec, } } -void ASTWriter::WriteASTCore(Sema &SemaRef, MemorizeStatCalls *StatCalls, +void ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot, const std::string &OutputFile, Module *WritingModule) { @@ -3597,8 +3556,6 @@ void ASTWriter::WriteASTCore(Sema &SemaRef, MemorizeStatCalls *StatCalls, // Write the remaining AST contents. RecordData Record; Stream.EnterSubblock(AST_BLOCK_ID, 5); - if (StatCalls && isysroot.empty()) - WriteStatCache(*StatCalls); // Create a lexical update block containing all of the declarations in the // translation unit that do not come from other AST files. diff --git a/clang/lib/Serialization/GeneratePCH.cpp b/clang/lib/Serialization/GeneratePCH.cpp index c2b353a..870d654 100644 --- a/clang/lib/Serialization/GeneratePCH.cpp +++ b/clang/lib/Serialization/GeneratePCH.cpp @@ -18,7 +18,6 @@ #include "clang/AST/ASTConsumer.h" #include "clang/Lex/Preprocessor.h" #include "clang/Basic/FileManager.h" -#include "clang/Basic/FileSystemStatCache.h" #include "llvm/Bitcode/BitstreamWriter.h" #include "llvm/Support/raw_ostream.h" #include @@ -32,11 +31,7 @@ PCHGenerator::PCHGenerator(const Preprocessor &PP, raw_ostream *OS) : PP(PP), OutputFile(OutputFile), Module(Module), isysroot(isysroot.str()), Out(OS), - SemaPtr(0), StatCalls(0), Stream(Buffer), Writer(Stream) { - // Install a stat() listener to keep track of all of the stat() - // calls. - StatCalls = new MemorizeStatCalls(); - PP.getFileManager().addStatCache(StatCalls, /*AtBeginning=*/false); + SemaPtr(0), Stream(Buffer), Writer(Stream) { } PCHGenerator::~PCHGenerator() { @@ -48,7 +43,7 @@ void PCHGenerator::HandleTranslationUnit(ASTContext &Ctx) { // Emit the PCH file assert(SemaPtr && "No Sema?"); - Writer.WriteAST(*SemaPtr, StatCalls, OutputFile, Module, isysroot); + Writer.WriteAST(*SemaPtr, OutputFile, Module, isysroot); // Write the generated bitstream to "Out". Out->write((char *)&Buffer.front(), Buffer.size()); diff --git a/clang/lib/Serialization/Module.cpp b/clang/lib/Serialization/Module.cpp index 09ea754..5e42ab4 100644 --- a/clang/lib/Serialization/Module.cpp +++ b/clang/lib/Serialization/Module.cpp @@ -41,7 +41,7 @@ ModuleFile::ModuleFile(ModuleKind Kind, unsigned Generation) FileSortedDecls(0), NumFileSortedDecls(0), RedeclarationsMap(0), LocalNumRedeclarationsInMap(0), ObjCCategoriesMap(0), LocalNumObjCCategoriesInMap(0), - LocalNumTypes(0), TypeOffsets(0), BaseTypeIndex(0), StatCache(0) + LocalNumTypes(0), TypeOffsets(0), BaseTypeIndex(0) {} ModuleFile::~ModuleFile() { diff --git a/clang/test/PCH/Inputs/case-insensitive-include.h b/clang/test/PCH/Inputs/case-insensitive-include.h new file mode 100644 index 0000000..60bdf36 --- /dev/null +++ b/clang/test/PCH/Inputs/case-insensitive-include.h @@ -0,0 +1,5 @@ +#pragma once + +struct S { + int x; +}; diff --git a/clang/test/PCH/case-insensitive-include.c b/clang/test/PCH/case-insensitive-include.c new file mode 100644 index 0000000..707de70 --- /dev/null +++ b/clang/test/PCH/case-insensitive-include.c @@ -0,0 +1,29 @@ +// REQUIRES: case-insensitive-filesystem + +// Test this without pch. +// RUN: cp %S/Inputs/case-insensitive-include.h %T +// RUN: %clang_cc1 -fsyntax-only %s -include %s -I %T -verify + +// Test with pch. +// RUN: %clang_cc1 -emit-pch -o %t.pch %s -I %T + +// Modify inode of the header. +// RUN: cp %T/case-insensitive-include.h %t.copy +// RUN: touch -r %T/case-insensitive-include.h %t.copy +// RUN: mv %t.copy %T/case-insensitive-include.h + +// RUN: %clang_cc1 -fsyntax-only %s -include-pch %t.pch -I %T -verify + +// expected-no-diagnostics + +#ifndef HEADER +#define HEADER + +#include "case-insensitive-include.h" +#include "Case-Insensitive-Include.h" + +#else + +#include "Case-Insensitive-Include.h" + +#endif diff --git a/clang/test/lit.cfg b/clang/test/lit.cfg index b22346e..3cbe013 100644 --- a/clang/test/lit.cfg +++ b/clang/test/lit.cfg @@ -4,6 +4,7 @@ import os import platform import re import subprocess +import tempfile # Configuration file for the 'lit' test runner. @@ -225,6 +226,17 @@ if platform.system() in ['Darwin']: if platform.system() not in ['Windows']: config.available_features.add('ansi-escape-sequences') +# Case-insensitive file system +def is_filesystem_case_insensitive(): + handle, path = tempfile.mkstemp(prefix='case-test') + isInsensitive = os.path.exists(path.upper()) + os.close(handle) + os.remove(path) + return isInsensitive + +if is_filesystem_case_insensitive(): + config.available_features.add('case-insensitive-filesystem') + # [PR8833] LLP64-incompatible tests if not re.match(r'^x86_64.*-(win32|mingw32)$', config.target_triple): config.available_features.add('LP64') -- 2.7.4