Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions clang/include/clang/Basic/DiagnosticSerializationKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,9 @@ def err_ast_file_not_found : Error<
def err_ast_file_out_of_date : Error<
"%select{PCH|module|precompiled}0 file '%1' is out of date and "
"needs to be rebuilt%select{|: %3}2">, DefaultFatal;
def err_ast_file_dependency_out_of_date : Error<
"%select{PCH|module|AST}0 file '%1' is out of date because "
"dependency '%2' has changed%select{|: %4}3">, DefaultFatal;
def err_ast_file_invalid : Error<
"file '%1' is not a valid %select{PCH|module|precompiled}0 file: %2">, DefaultFatal;
def note_module_file_imported_by : Note<
Expand Down
5 changes: 4 additions & 1 deletion clang/include/clang/Serialization/ModuleManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,10 @@ class ModuleManager {
Missing,

/// The module file is out-of-date.
OutOfDate
OutOfDate,

/// The importer file is out-of-date
ImporterOutOfDate
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Importee

};

using ASTFileSignatureReader = ASTFileSignature (*)(StringRef);
Expand Down
14 changes: 14 additions & 0 deletions clang/lib/Serialization/ASTReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5139,6 +5139,20 @@ ASTReader::ReadASTCore(StringRef FileName,
<< moduleKindForDiagnostic(Type) << FileName << !ErrorStr.empty()
<< ErrorStr;
return Failure;

case ModuleManager::ImporterOutOfDate:
// We couldn't load the module file because it is out-of-date. If the
// client can handle out-of-date, return it.
if (ClientLoadCapabilities & ARR_OutOfDate)
return OutOfDate;

// Otherwise, report that the importer is out of date because the dependency
// changed.
if (ImportedBy)
Diag(diag::err_ast_file_dependency_out_of_date)
<< moduleKindForDiagnostic(ImportedBy->Kind) << ImportedBy->FileName
<< FileName << !ErrorStr.empty() << StringRef(ErrorStr);
return Failure;
}

assert(M && "Missing module file");
Expand Down
6 changes: 3 additions & 3 deletions clang/lib/Serialization/ModuleManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ ModuleManager::addModule(StringRef FileName, ModuleKind Type,
ErrorStr = IgnoreModTime ? "module file has a different size than expected"
: "module file has a different size or "
"modification time than expected";
return OutOfDate;
return ImporterOutOfDate;
}

if (!Entry) {
Expand Down Expand Up @@ -159,7 +159,7 @@ ModuleManager::addModule(StringRef FileName, ModuleKind Type,
if (implicitModuleNamesMatch(Type, ModuleEntry, *Entry)) {
// Check the stored signature.
if (checkSignature(ModuleEntry->Signature, ExpectedSignature, ErrorStr))
return OutOfDate;
return ImporterOutOfDate;

Module = ModuleEntry;
updateModuleImports(*ModuleEntry, ImportedBy, ImportLoc);
Expand Down Expand Up @@ -226,7 +226,7 @@ ModuleManager::addModule(StringRef FileName, ModuleKind Type,
// ReadSignature unless there's something to check though.
if (ExpectedSignature && checkSignature(ReadSignature(NewModule->Data),
ExpectedSignature, ErrorStr))
return OutOfDate;
return ImporterOutOfDate;

// We're keeping this module. Store it everywhere.
Module = Modules[*Entry] = NewModule.get();
Expand Down
42 changes: 41 additions & 1 deletion clang/test/Modules/explicit-build.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,46 @@
// CHECK-NO-FILE-INDIRECT-NEXT: note: imported by module 'c' in '{{.*}}c.pcm'
// CHECK-NO-FILE-INDIRECT-NOT: note:

// -------------------------------
// Check that we diagnose stale dependencies correctly when modules change.
//
// Trigger a rebuild of A with a different configuration (-DA_EXTRA_DEFINE) to make B and C out of date
// RUN: mv %t/a.pcm %t/a-tmp.pcm
// RUN: %clang_cc1 -x c++ -std=c++11 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -Rmodule-build -fno-modules-error-recovery \
// RUN: -fmodule-name=a -emit-module %S/Inputs/explicit-build/module.modulemap -o %t/a.pcm \
// RUN: -DA_EXTRA_DEFINE \
// RUN: 2>&1 | FileCheck --check-prefix=CHECK-NO-IMPLICIT-BUILD %s --allow-empty

// Try to use C, which depends on B, which depends on the now-changed A.
// RUN: not %clang_cc1 -x c++ -std=c++11 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -Rmodule-build -fno-modules-error-recovery \
// RUN: -I%S/Inputs/explicit-build \
// RUN: -fmodule-file=%t/c.pcm \
// RUN: %s -DHAVE_A -DHAVE_B -DHAVE_C 2>&1 | FileCheck --check-prefix=CHECK-OUT-OF-DATE-INDIRECT %s
//
// CHECK-OUT-OF-DATE-INDIRECT: fatal error: module file '{{.*}}b.pcm' is out of date because dependency '{{.*}}a.pcm' has changed
// CHECK-OUT-OF-DATE-INDIRECT-NEXT: note: imported by module 'b' in '{{.*}}b.pcm'
// CHECK-OUT-OF-DATE-INDIRECT-NEXT: note: imported by module 'c' in '{{.*}}c.pcm'

// Rebuild B with the new A, leaving C out of date.
// RUN: mv %t/b.pcm %t/b-tmp.pcm
// RUN: %clang_cc1 -x c++ -std=c++11 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -Rmodule-build -fno-modules-error-recovery \
// RUN: -fmodule-file=%t/a.pcm \
// RUN: -fmodule-name=b -emit-module %S/Inputs/explicit-build/module.modulemap -o %t/b.pcm \
// RUN: -DA_EXTRA_DEFINE \
// RUN: 2>&1 | FileCheck --check-prefix=CHECK-NO-IMPLICIT-BUILD %s --allow-empty
//
// Now only C is out of date. Try to use C.
// RUN: not %clang_cc1 -x c++ -std=c++11 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -Rmodule-build -fno-modules-error-recovery \
// RUN: -I%S/Inputs/explicit-build \
// RUN: -fmodule-file=%t/c.pcm \
// RUN: %s -DHAVE_A -DHAVE_B -DHAVE_C 2>&1 | FileCheck --check-prefix=CHECK-OUT-OF-DATE-DIRECT %s
//
// CHECK-OUT-OF-DATE-DIRECT: fatal error: module file '{{.*}}c.pcm' is out of date because dependency '{{.*}}b.pcm' has changed
// CHECK-OUT-OF-DATE-DIRECT-NOT: fatal error: module file '{{.*}}b.pcm' is out of date
//
// RUN: mv %t/a-tmp.pcm %t/a.pcm
// RUN: mv %t/b-tmp.pcm %t/b.pcm

// -------------------------------
// Check that we don't get upset if B's timestamp is newer than C's.
// RUN: touch %t/b.pcm
Expand All @@ -202,6 +242,6 @@
// RUN: -fmodule-file=%t/c.pcm \
// RUN: %s -DHAVE_A -DHAVE_B -DHAVE_C 2>&1 | FileCheck --check-prefix=CHECK-MISMATCHED-B %s
//
// CHECK-MISMATCHED-B: fatal error: module file '{{.*}}b.pcm' is out of date and needs to be rebuilt: module file has a different size than expected
// CHECK-MISMATCHED-B: fatal error: module file '{{.*}}c.pcm' is out of date because dependency '{{.*}}b.pcm' has changed: module file has a different size than expected
// CHECK-MISMATCHED-B-NEXT: note: imported by module 'c'
// CHECK-MISMATCHED-B-NOT: note:
2 changes: 1 addition & 1 deletion clang/test/Modules/invalid-module-dep.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
#include <A/A.h>
#include <B/B.h> // expected-warning {{conflicts with imported file}} \
// expected-note {{imported by module 'B'}} \
// expected-error {{out of date and needs to be rebuilt}}
// expected-error {{is out of date because dependency}}

//--- Sysroot/usr/include/A/module.modulemap
module A [system] {
Expand Down
Loading