summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/include/clang/Frontend/FrontendOptions.h3
-rw-r--r--clang/include/clang/Serialization/ASTWriter.h16
-rw-r--r--clang/include/clang/Serialization/Module.h3
-rw-r--r--clang/lib/Frontend/CompilerInstance.cpp1
-rw-r--r--clang/lib/Frontend/FrontendActions.cpp4
-rw-r--r--clang/lib/Serialization/ASTReader.cpp22
-rw-r--r--clang/lib/Serialization/ASTReaderInternals.h2
-rw-r--r--clang/lib/Serialization/ASTWriter.cpp38
-rw-r--r--clang/lib/Serialization/GeneratePCH.cpp5
-rw-r--r--clang/test/Modules/explicit-build-missing-files.cpp4
-rw-r--r--clang/test/Modules/module-map-path-hash.cpp2
11 files changed, 63 insertions, 37 deletions
diff --git a/clang/include/clang/Frontend/FrontendOptions.h b/clang/include/clang/Frontend/FrontendOptions.h
index 909dcc5e8e2..cc555860bba 100644
--- a/clang/include/clang/Frontend/FrontendOptions.h
+++ b/clang/include/clang/Frontend/FrontendOptions.h
@@ -147,6 +147,8 @@ public:
///< dumps in AST dumps.
unsigned ASTDumpLookups : 1; ///< Whether we include lookup table
///< dumps in AST dumps.
+ unsigned BuildingImplicitModule : 1; ///< Whether we are performing an
+ ///< implicit module build.
CodeCompleteOptions CodeCompleteOpts;
@@ -263,6 +265,7 @@ public:
FixToTemporaries(false), ARCMTMigrateEmitARCErrors(false),
SkipFunctionBodies(false), UseGlobalModuleIndex(true),
GenerateGlobalModuleIndex(true), ASTDumpDecls(false), ASTDumpLookups(false),
+ BuildingImplicitModule(false),
ARCMTAction(ARCMT_None), ObjCMTAction(ObjCMT_None),
ProgramAction(frontend::ParseSyntaxOnly)
{}
diff --git a/clang/include/clang/Serialization/ASTWriter.h b/clang/include/clang/Serialization/ASTWriter.h
index e830fdcf8f2..7cb91b4de16 100644
--- a/clang/include/clang/Serialization/ASTWriter.h
+++ b/clang/include/clang/Serialization/ASTWriter.h
@@ -119,6 +119,12 @@ private:
/// \brief The base directory for any relative paths we emit.
std::string BaseDirectory;
+ /// \brief Indicates whether timestamps should be written to the produced
+ /// module file. This is the case for files implicitly written to the
+ /// module cache, where we need the timestamps to determine if the module
+ /// file is up to date, but not otherwise.
+ bool IncludeTimestamps;
+
/// \brief Indicates when the AST writing is actively performing
/// serialization, rather than just queueing updates.
bool WritingAST;
@@ -569,11 +575,16 @@ private:
public:
/// \brief Create a new precompiled header writer that outputs to
/// the given bitstream.
- ASTWriter(llvm::BitstreamWriter &Stream);
+ ASTWriter(llvm::BitstreamWriter &Stream, bool IncludeTimestamps = true);
~ASTWriter() override;
const LangOptions &getLangOpts() const;
+ /// \brief Get a timestamp for output into the AST file. The actual timestamp
+ /// of the specified file may be ignored if we have been instructed to not
+ /// include timestamps in the output file.
+ time_t getTimestampForOutput(const FileEntry *E) const;
+
/// \brief Write a precompiled header for the given semantic analysis.
///
/// \param SemaRef a reference to the semantic analysis object that processed
@@ -892,7 +903,8 @@ public:
PCHGenerator(const Preprocessor &PP, StringRef OutputFile,
clang::Module *Module, StringRef isysroot,
std::shared_ptr<PCHBuffer> Buffer,
- bool AllowASTWithErrors = false);
+ bool AllowASTWithErrors = false,
+ bool IncludeTimestamps = true);
~PCHGenerator() override;
void InitializeSema(Sema &S) override { SemaPtr = &S; }
void HandleTranslationUnit(ASTContext &Ctx) override;
diff --git a/clang/include/clang/Serialization/Module.h b/clang/include/clang/Serialization/Module.h
index 0740cd025ec..ee10f9b7e4d 100644
--- a/clang/include/clang/Serialization/Module.h
+++ b/clang/include/clang/Serialization/Module.h
@@ -152,6 +152,9 @@ public:
/// \brief Whether this precompiled header is a relocatable PCH file.
bool RelocatablePCH;
+ /// \brief Whether timestamps are included in this module file.
+ bool HasTimestamps;
+
/// \brief The file entry for the module file.
const FileEntry *File;
diff --git a/clang/lib/Frontend/CompilerInstance.cpp b/clang/lib/Frontend/CompilerInstance.cpp
index c678da982ed..5079353226c 100644
--- a/clang/lib/Frontend/CompilerInstance.cpp
+++ b/clang/lib/Frontend/CompilerInstance.cpp
@@ -913,6 +913,7 @@ static bool compileModuleImpl(CompilerInstance &ImportingInstance,
FrontendOpts.OutputFile = ModuleFileName.str();
FrontendOpts.DisableFree = false;
FrontendOpts.GenerateGlobalModuleIndex = false;
+ FrontendOpts.BuildingImplicitModule = true;
FrontendOpts.Inputs.clear();
InputKind IK = getSourceInputKindFromOptions(*Invocation->getLangOpts());
diff --git a/clang/lib/Frontend/FrontendActions.cpp b/clang/lib/Frontend/FrontendActions.cpp
index 057361811ba..782b713d3e2 100644
--- a/clang/lib/Frontend/FrontendActions.cpp
+++ b/clang/lib/Frontend/FrontendActions.cpp
@@ -137,7 +137,9 @@ GenerateModuleAction::CreateASTConsumer(CompilerInstance &CI,
auto Buffer = std::make_shared<PCHBuffer>();
std::vector<std::unique_ptr<ASTConsumer>> Consumers;
Consumers.push_back(llvm::make_unique<PCHGenerator>(
- CI.getPreprocessor(), OutputFile, Module, Sysroot, Buffer));
+ CI.getPreprocessor(), OutputFile, Module, Sysroot, Buffer,
+ /*AllowASTWithErrors*/false,
+ /*IncludeTimestamps*/+CI.getFrontendOpts().BuildingImplicitModule));
Consumers.push_back(
CI.getPCHContainerWriter().CreatePCHContainerGenerator(
CI.getDiagnostics(), CI.getHeaderSearchOpts(),
diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp
index 547dda73f73..6d41d155c56 100644
--- a/clang/lib/Serialization/ASTReader.cpp
+++ b/clang/lib/Serialization/ASTReader.cpp
@@ -1500,13 +1500,14 @@ unsigned HeaderFileInfoTrait::ComputeHash(internal_key_ref ikey) {
HeaderFileInfoTrait::internal_key_type
HeaderFileInfoTrait::GetInternalKey(const FileEntry *FE) {
- internal_key_type ikey = { FE->getSize(), FE->getModificationTime(),
- FE->getName(), /*Imported*/false };
+ internal_key_type ikey = {FE->getSize(),
+ M.HasTimestamps ? FE->getModificationTime() : 0,
+ FE->getName(), /*Imported*/ false};
return ikey;
}
bool HeaderFileInfoTrait::EqualKey(internal_key_ref a, internal_key_ref b) {
- if (a.Size != b.Size || a.ModTime != b.ModTime)
+ if (a.Size != b.Size || (a.ModTime && b.ModTime && a.ModTime != b.ModTime))
return false;
if (llvm::sys::path::is_absolute(a.Filename) &&
@@ -1976,14 +1977,9 @@ InputFile ASTReader::getInputFile(ModuleFile &F, unsigned ID, bool Complain) {
// have inconsistent modification times that sometimes
// erroneously trigger this error-handling path.
//
- // This also happens in networked file systems, so disable this
- // check if validation is disabled or if we have an explicitly
- // built PCM file.
- //
- // FIXME: Should we also do this for PCH files? They could also
- // reasonably get shared across a network during a distributed build.
- (StoredTime != File->getModificationTime() && !DisableValidation &&
- F.Kind != MK_ExplicitModule)
+ // FIXME: This probably also breaks HeaderFileInfo lookups on Windows.
+ (StoredTime && StoredTime != File->getModificationTime() &&
+ !DisableValidation)
#endif
)) {
if (Complain) {
@@ -2164,7 +2160,7 @@ ASTReader::ReadControlBlock(ModuleFile &F,
return VersionMismatch;
}
- bool hasErrors = Record[5];
+ bool hasErrors = Record[6];
if (hasErrors && !DisableValidation && !AllowASTWithCompilerErrors) {
Diag(diag::err_pch_with_compiler_errors);
return HadErrors;
@@ -2175,6 +2171,8 @@ ASTReader::ReadControlBlock(ModuleFile &F,
if (F.RelocatablePCH)
F.BaseDirectory = isysroot.empty() ? "/" : isysroot;
+ F.HasTimestamps = Record[5];
+
const std::string &CurBranch = getClangFullRepositoryVersion();
StringRef ASTBranch = Blob;
if (StringRef(CurBranch) != ASTBranch && !DisableValidation) {
diff --git a/clang/lib/Serialization/ASTReaderInternals.h b/clang/lib/Serialization/ASTReaderInternals.h
index 5b1c4f4963e..701cf7300f6 100644
--- a/clang/lib/Serialization/ASTReaderInternals.h
+++ b/clang/lib/Serialization/ASTReaderInternals.h
@@ -226,7 +226,7 @@ public:
: Reader(Reader), M(M), HS(HS), FrameworkStrings(FrameworkStrings) { }
static hash_value_type ComputeHash(internal_key_ref ikey);
- static internal_key_type GetInternalKey(const FileEntry *FE);
+ internal_key_type GetInternalKey(const FileEntry *FE);
bool EqualKey(internal_key_ref a, internal_key_ref b);
static std::pair<unsigned, unsigned>
diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp
index 566c7d7c9f2..b774abe17e1 100644
--- a/clang/lib/Serialization/ASTWriter.cpp
+++ b/clang/lib/Serialization/ASTWriter.cpp
@@ -1148,6 +1148,7 @@ void ASTWriter::WriteControlBlock(Preprocessor &PP, ASTContext &Context,
MetadataAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Clang maj.
MetadataAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Clang min.
MetadataAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Relocatable
+ MetadataAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Timestamps
MetadataAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Errors
MetadataAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // SVN branch/tag
unsigned MetadataAbbrevCode = Stream.EmitAbbrev(MetadataAbbrev);
@@ -1159,6 +1160,7 @@ void ASTWriter::WriteControlBlock(Preprocessor &PP, ASTContext &Context,
assert((!WritingModule || isysroot.empty()) &&
"writing module as a relocatable PCH?");
Record.push_back(!isysroot.empty());
+ Record.push_back(IncludeTimestamps);
Record.push_back(ASTHasCompilerErrors);
Stream.EmitRecordWithBlob(MetadataAbbrevCode, Record,
getClangFullRepositoryVersion());
@@ -1248,7 +1250,7 @@ void ASTWriter::WriteControlBlock(Preprocessor &PP, ASTContext &Context,
Record.push_back((unsigned)M->Kind); // FIXME: Stable encoding
AddSourceLocation(M->ImportLoc, Record);
Record.push_back(M->File->getSize());
- Record.push_back(M->File->getModificationTime());
+ Record.push_back(getTimestampForOutput(M->File));
Record.push_back(M->Signature);
AddPath(M->FileName, Record);
}
@@ -1512,7 +1514,7 @@ void ASTWriter::WriteInputFiles(SourceManager &SourceMgr,
// Emit size/modification time for this file.
Record.push_back(Entry.File->getSize());
- Record.push_back(Entry.File->getModificationTime());
+ Record.push_back(getTimestampForOutput(Entry.File));
// Whether this file was overridden.
Record.push_back(Entry.BufferOverridden);
@@ -1624,15 +1626,12 @@ namespace {
typedef unsigned hash_value_type;
typedef unsigned offset_type;
- static hash_value_type ComputeHash(key_type_ref key) {
+ hash_value_type ComputeHash(key_type_ref key) {
// The hash is based only on size/time of the file, so that the reader can
// match even when symlinking or excess path elements ("foo/../", "../")
// change the form of the name. However, complete path is still the key.
- //
- // FIXME: Using the mtime here will cause problems for explicit module
- // imports.
return llvm::hash_combine(key.FE->getSize(),
- key.FE->getModificationTime());
+ Writer.getTimestampForOutput(key.FE));
}
std::pair<unsigned,unsigned>
@@ -1653,7 +1652,7 @@ namespace {
endian::Writer<little> LE(Out);
LE.write<uint64_t>(key.FE->getSize());
KeyLen -= 8;
- LE.write<uint64_t>(key.FE->getModificationTime());
+ LE.write<uint64_t>(Writer.getTimestampForOutput(key.FE));
KeyLen -= 8;
Out.write(key.Filename, KeyLen);
}
@@ -4058,22 +4057,21 @@ void ASTWriter::SetSelectorOffset(Selector Sel, uint32_t Offset) {
SelectorOffsets[ID - FirstSelectorID] = Offset;
}
-ASTWriter::ASTWriter(llvm::BitstreamWriter &Stream)
+ASTWriter::ASTWriter(llvm::BitstreamWriter &Stream, bool IncludeTimestamps)
: Stream(Stream), Context(nullptr), PP(nullptr), Chain(nullptr),
- WritingModule(nullptr), WritingAST(false),
- DoneWritingDeclsAndTypes(false), ASTHasCompilerErrors(false),
- FirstDeclID(NUM_PREDEF_DECL_IDS), NextDeclID(FirstDeclID),
- FirstTypeID(NUM_PREDEF_TYPE_IDS), NextTypeID(FirstTypeID),
- FirstIdentID(NUM_PREDEF_IDENT_IDS), NextIdentID(FirstIdentID),
- FirstMacroID(NUM_PREDEF_MACRO_IDS), NextMacroID(FirstMacroID),
- FirstSubmoduleID(NUM_PREDEF_SUBMODULE_IDS),
+ WritingModule(nullptr), IncludeTimestamps(IncludeTimestamps),
+ WritingAST(false), DoneWritingDeclsAndTypes(false),
+ ASTHasCompilerErrors(false), FirstDeclID(NUM_PREDEF_DECL_IDS),
+ NextDeclID(FirstDeclID), FirstTypeID(NUM_PREDEF_TYPE_IDS),
+ NextTypeID(FirstTypeID), FirstIdentID(NUM_PREDEF_IDENT_IDS),
+ NextIdentID(FirstIdentID), FirstMacroID(NUM_PREDEF_MACRO_IDS),
+ NextMacroID(FirstMacroID), FirstSubmoduleID(NUM_PREDEF_SUBMODULE_IDS),
NextSubmoduleID(FirstSubmoduleID),
FirstSelectorID(NUM_PREDEF_SELECTOR_IDS), NextSelectorID(FirstSelectorID),
CollectedStmts(&StmtsToEmit), NumStatements(0), NumMacros(0),
NumLexicalDeclContexts(0), NumVisibleDeclContexts(0),
NextCXXBaseSpecifiersID(1), NextCXXCtorInitializersID(1),
- TypeExtQualAbbrev(0),
- TypeFunctionProtoAbbrev(0), DeclParmVarAbbrev(0),
+ TypeExtQualAbbrev(0), TypeFunctionProtoAbbrev(0), DeclParmVarAbbrev(0),
DeclContextLexicalAbbrev(0), DeclContextVisibleLookupAbbrev(0),
UpdateVisibleAbbrev(0), DeclRecordAbbrev(0), DeclTypedefAbbrev(0),
DeclVarAbbrev(0), DeclFieldAbbrev(0), DeclEnumAbbrev(0),
@@ -4090,6 +4088,10 @@ const LangOptions &ASTWriter::getLangOpts() const {
return Context->getLangOpts();
}
+time_t ASTWriter::getTimestampForOutput(const FileEntry *E) const {
+ return IncludeTimestamps ? E->getModificationTime() : 0;
+}
+
void ASTWriter::WriteAST(Sema &SemaRef,
const std::string &OutputFile,
Module *WritingModule, StringRef isysroot,
diff --git a/clang/lib/Serialization/GeneratePCH.cpp b/clang/lib/Serialization/GeneratePCH.cpp
index c461fe936ee..08660bc9675 100644
--- a/clang/lib/Serialization/GeneratePCH.cpp
+++ b/clang/lib/Serialization/GeneratePCH.cpp
@@ -26,9 +26,10 @@ using namespace clang;
PCHGenerator::PCHGenerator(const Preprocessor &PP, StringRef OutputFile,
clang::Module *Module, StringRef isysroot,
std::shared_ptr<PCHBuffer> Buffer,
- bool AllowASTWithErrors)
+ bool AllowASTWithErrors, bool IncludeTimestamps)
: PP(PP), OutputFile(OutputFile), Module(Module), isysroot(isysroot.str()),
- SemaPtr(nullptr), Buffer(Buffer), Stream(Buffer->Data), Writer(Stream),
+ SemaPtr(nullptr), Buffer(Buffer), Stream(Buffer->Data),
+ Writer(Stream, IncludeTimestamps),
AllowASTWithErrors(AllowASTWithErrors) {
Buffer->IsComplete = false;
}
diff --git a/clang/test/Modules/explicit-build-missing-files.cpp b/clang/test/Modules/explicit-build-missing-files.cpp
index ff79a116e6b..b2730e4f227 100644
--- a/clang/test/Modules/explicit-build-missing-files.cpp
+++ b/clang/test/Modules/explicit-build-missing-files.cpp
@@ -21,6 +21,10 @@
// RUN: rm %t/other.modulemap
// RUN: %clang_cc1 -fmodules -I %t -fmodule-file=%t/a.pcm %s
// RUN: not %clang_cc1 -fmodules -I %t -fmodule-file=%t/a.pcm %s -DERRORS 2>&1 | FileCheck %s
+// RUN: sleep 1
+// RUN: touch %t/a.h
+// RUN: %clang_cc1 -fmodules -I %t -fmodule-file=%t/a.pcm %s
+// RUN: not %clang_cc1 -fmodules -I %t -fmodule-file=%t/a.pcm %s -DERRORS 2>&1 | FileCheck %s
// RUN: rm %t/b.h
// RUN: %clang_cc1 -fmodules -I %t -fmodule-file=%t/a.pcm %s
// RUN: not %clang_cc1 -fmodules -I %t -fmodule-file=%t/a.pcm %s -DERRORS 2>&1 | FileCheck %s --check-prefix=MISSING-B
diff --git a/clang/test/Modules/module-map-path-hash.cpp b/clang/test/Modules/module-map-path-hash.cpp
index 620e428a2f0..ccfa96ebd25 100644
--- a/clang/test/Modules/module-map-path-hash.cpp
+++ b/clang/test/Modules/module-map-path-hash.cpp
@@ -1,4 +1,4 @@
-// rm -rf %t
+// RUN: rm -rf %t
// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -x c++ -Rmodule-build -I%S/Inputs/module-map-path-hash -fmodules-cache-path=%t -fsyntax-only %s
// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -x c++ -Rmodule-build -I%S/Inputs//module-map-path-hash -fmodules-cache-path=%t -fsyntax-only %s 2>&1 | FileCheck -allow-empty %s
// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -x c++ -Rmodule-build -I%S/Inputs/./module-map-path-hash -fmodules-cache-path=%t -fsyntax-only %s 2>&1 | FileCheck -allow-empty %s
OpenPOWER on IntegriCloud