[flang-commits] [clang] [flang] [Flang] Optionally turn module checksum check into warning (PR #219181)
Michael Kruse via flang-commits
flang-commits at lists.llvm.org
Thu Aug 27 04:16:50 PDT 2026
https://github.com/Meinersbur created https://github.com/llvm/llvm-project/pull/219181
Add `-fmodule-mismatch-check` option:
* `-fmodule-mismatch-check=on`: Current behavior: error when a module mismatch is detected
* `-fmodule-mismatch-check=non-intrinsic`: Error when a user module mismatches, but ignore intrinsic module mismatches. Flang consideres a module being an intrinsic primarily by what modifier is on the `USE` statement, but if that is missing, uses in which search path it was found.
* `-fmodule-mismatch-check=warn`: Only warn about mismatches, but continue compiling
* `-fmodule-mismatch-check=warn -Wno-module-file-mismatch`: Complete silence on mismatch
Normally, when loading a .mod file, Flang checks whether the modules it itself depends on are the same modules from when the .mod file was created. If there is a mismatch, compilation fails. The option converts this error into a warning instead. The warning can be silenced using -Wno-module-file-mismatch and thus mismatches are completely ignored. -fmodule-mismatch-check=non-intrinsic still keeps the error for user modules where mismatches hint towards a build dependency problem. Mismatches of intrinsic modules are expected after a compiler upgrade. Upgraded intrinsic modules are supposed to be backwards-compatible.
>From 5571568b3d049283ab6672c297c34f5800cf69d4 Mon Sep 17 00:00:00 2001
From: Michael Kruse <llvm-project at meinersbur.de>
Date: Wed, 26 Aug 2026 13:23:03 +0200
Subject: [PATCH 1/2] Implement -fmodule-mismatch-check
flang_driver_module-mismatch-option
Handle non-existing checksum as well
Handle only checksum mismatch
---
clang/include/clang/Options/FlangOptions.td | 2 +
clang/lib/Driver/ToolChains/Flang.cpp | 1 +
.../include/flang/Support/Fortran-features.h | 16 +++----
flang/include/flang/Support/LangOptions.def | 2 +
flang/include/flang/Support/LangOptions.h | 14 ++++++
flang/lib/Frontend/CompilerInvocation.cpp | 20 ++++++++
flang/lib/Semantics/mod-file.cpp | 47 +++++++++++++++++--
flang/lib/Semantics/mod-file.h | 2 +
flang/lib/Support/Fortran-features.cpp | 1 +
.../Inputs/dir1/module_mismatch_check_a.mod | 6 +++
.../Inputs/dir2/module_mismatch_check_a.mod | 8 ++++
.../Inputs/module_mismatch_check_b.mod | 8 ++++
.../module-mismatch-check-intrinsic.f90 | 27 +++++++++++
.../Semantics/module-mismatch-check-user.f90 | 32 +++++++++++++
14 files changed, 173 insertions(+), 13 deletions(-)
create mode 100644 flang/test/Semantics/Inputs/dir1/module_mismatch_check_a.mod
create mode 100644 flang/test/Semantics/Inputs/dir2/module_mismatch_check_a.mod
create mode 100644 flang/test/Semantics/Inputs/module_mismatch_check_b.mod
create mode 100644 flang/test/Semantics/module-mismatch-check-intrinsic.f90
create mode 100644 flang/test/Semantics/module-mismatch-check-user.f90
diff --git a/clang/include/clang/Options/FlangOptions.td b/clang/include/clang/Options/FlangOptions.td
index 7a3dfd84fd4e7..980508ba98947 100644
--- a/clang/include/clang/Options/FlangOptions.td
+++ b/clang/include/clang/Options/FlangOptions.td
@@ -137,6 +137,8 @@ def module_dir : JoinedOrSeparate<["-"], "module-dir">, MetaVarName<"<dir>">,
DocBrief<[{This option specifies where to put .mod files for compiled modules.
It is also added to the list of directories to be searched by an USE statement.
The default is the current directory.}]>;
+def fmodule_mismatch_check_EQ : Joined<["-"], "fmodule-mismatch-check=">, Group<f_Group>,
+ HelpText<"Check consistency of used modules (option: on, non-intrinsic, warn)">;
def ffixed_form : Flag<["-"], "ffixed-form">, Group<f_Group>,
HelpText<"Process source files in fixed form">;
diff --git a/clang/lib/Driver/ToolChains/Flang.cpp b/clang/lib/Driver/ToolChains/Flang.cpp
index 7e7ac97b8b0e5..3404580ac1206 100644
--- a/clang/lib/Driver/ToolChains/Flang.cpp
+++ b/clang/lib/Driver/ToolChains/Flang.cpp
@@ -152,6 +152,7 @@ void Flang::addFortranDialectOptions(const ArgList &Args,
options::OPT_fdefault_integer_8,
options::OPT_fdefault_double_8,
options::OPT_flarge_sizes,
+ options::OPT_fmodule_mismatch_check_EQ,
options::OPT_fno_automatic,
options::OPT_fhermetic_module_files,
options::OPT_frealloc_lhs,
diff --git a/flang/include/flang/Support/Fortran-features.h b/flang/include/flang/Support/Fortran-features.h
index 4921496adee5c..1a646c8bfa789 100644
--- a/flang/include/flang/Support/Fortran-features.h
+++ b/flang/include/flang/Support/Fortran-features.h
@@ -81,14 +81,14 @@ ENUM_CLASS(UsageWarning, Portability, PointerToUndefinable,
IndexVarRedefinition, IncompatibleImplicitInterfaces,
VectorSubscriptFinalization, UndefinedFunctionResult, UselessIomsg,
MismatchingDummyProcedure, SubscriptedEmptyArray, UnsignedLiteralTruncation,
- CompatibleDeclarationsFromDistinctModules, ConstantIsContiguous,
- NullActualForDefaultIntentAllocatable, UseAssociationIntoSameNameSubprogram,
- HostAssociatedIntentOutInSpecExpr, NonVolatilePointerToVolatile,
- RealConstantWidening, VolatileOrAsynchronousTemporary, UnusedVariable,
- UsedUndefinedVariable, BadValueInDeadCode, AssumedTypeSizeDummy,
- MisplacedIgnoreTKR, NamelistParameter, ImpureFinalInPure,
- IgnoredNoReallocateLHS, ExperimentalOption, IoImpliedDoIndexConflict,
- BOZLiteralTruncation)
+ CompatibleDeclarationsFromDistinctModules, ModuleFileMismatch,
+ ConstantIsContiguous, NullActualForDefaultIntentAllocatable,
+ UseAssociationIntoSameNameSubprogram, HostAssociatedIntentOutInSpecExpr,
+ NonVolatilePointerToVolatile, RealConstantWidening,
+ VolatileOrAsynchronousTemporary, UnusedVariable, UsedUndefinedVariable,
+ BadValueInDeadCode, AssumedTypeSizeDummy, MisplacedIgnoreTKR,
+ NamelistParameter, ImpureFinalInPure, IgnoredNoReallocateLHS,
+ ExperimentalOption, IoImpliedDoIndexConflict, BOZLiteralTruncation)
using LanguageFeatures = EnumSet<LanguageFeature, LanguageFeature_enumSize>;
using UsageWarnings = EnumSet<UsageWarning, UsageWarning_enumSize>;
diff --git a/flang/include/flang/Support/LangOptions.def b/flang/include/flang/Support/LangOptions.def
index 80d2302cc8c72..ed41f2b717e23 100644
--- a/flang/include/flang/Support/LangOptions.def
+++ b/flang/include/flang/Support/LangOptions.def
@@ -22,6 +22,8 @@ LANGOPT(Name, Bits, Default)
ENUM_LANGOPT(FPContractMode, FPModeKind, 2, FPM_Fast) ///< FP Contract Mode (off/fast)
/// signed integer overflow handling
ENUM_LANGOPT(SignedOverflowBehavior, SignedOverflowBehaviorTy, 1, SOB_Undefined)
+/// Module file checksum mismatch handling
+ENUM_LANGOPT(ModuleMismatchCheck, ModuleMismatchCheckTy, 2, MMC_On)
/// Indicate a build without the standard GPU libraries.
LANGOPT(NoGPULib , 1, false)
diff --git a/flang/include/flang/Support/LangOptions.h b/flang/include/flang/Support/LangOptions.h
index 42b488c3d18a3..2e2196858cecd 100644
--- a/flang/include/flang/Support/LangOptions.h
+++ b/flang/include/flang/Support/LangOptions.h
@@ -43,6 +43,20 @@ class LangOptionsBase {
FPM_Fast,
};
+ enum ModuleMismatchCheckTy {
+ // Verify checksums of all modules
+ MMC_On,
+
+ // Reject checksum mismatches only in user modules. Intrinsic modules are
+ // shipped by the compiler, and their contents are defined by the language;
+ // a compiler update should not trigger an error when their APIs remain
+ // compatible.
+ MMC_NonIntrinsic,
+
+ // Do not enforce module use consistency, just warn about them
+ MMC_Warn,
+ };
+
/// Floating-point exception trap kinds for -ffpe-trap=.
/// Bit values match the Fortran IEEE_FLAG_TYPE encoding used by
/// the runtime's MapException().
diff --git a/flang/lib/Frontend/CompilerInvocation.cpp b/flang/lib/Frontend/CompilerInvocation.cpp
index 87a25f3101ddd..5b6a80c1d3635 100644
--- a/flang/lib/Frontend/CompilerInvocation.cpp
+++ b/flang/lib/Frontend/CompilerInvocation.cpp
@@ -1064,6 +1064,26 @@ static bool parseSemaArgs(CompilerInvocation &res, llvm::opt::ArgList &args,
if (moduleDirList.size() == 1)
res.setModuleDir(moduleDirList[0]);
+ // -fmodule-mismatch-check=<value>
+ if (const auto *arg =
+ args.getLastArg(clang::options::OPT_fmodule_mismatch_check_EQ)) {
+ using ModuleMismatchCheckTy =
+ Fortran::common::LangOptions::ModuleMismatchCheckTy;
+ auto check = llvm::StringSwitch<std::optional<ModuleMismatchCheckTy>>(
+ arg->getValue())
+ .Case("on", Fortran::common::LangOptions::MMC_On)
+ .Case("warn", Fortran::common::LangOptions::MMC_Warn)
+ .Case("non-intrinsic",
+ Fortran::common::LangOptions::MMC_NonIntrinsic)
+ .Default(std::nullopt);
+ if (check) {
+ res.getLangOpts().setModuleMismatchCheck(*check);
+ } else {
+ diags.Report(clang::diag::err_drv_invalid_value)
+ << arg->getAsString(args) << arg->getValue();
+ }
+ }
+
// -fdebug-module-writer option
if (args.hasArg(clang::options::OPT_fdebug_module_writer)) {
res.setDebugModuleDir(true);
diff --git a/flang/lib/Semantics/mod-file.cpp b/flang/lib/Semantics/mod-file.cpp
index e0fabd989bb45..5e9b1d1da00b1 100644
--- a/flang/lib/Semantics/mod-file.cpp
+++ b/flang/lib/Semantics/mod-file.cpp
@@ -1744,6 +1744,21 @@ Scope *ModFileReader::Read(SourceName name, std::optional<bool> isIntrinsic,
return nullptr;
}
CHECK(sourceFile);
+
+ bool mismatchIsError, mismatchIsWarning;
+ switch (context_.langOptions().getModuleMismatchCheck()) {
+ case common::LangOptions::MMC_On:
+ mismatchIsError = true;
+ mismatchIsWarning = true;
+ break;
+ case common::LangOptions::MMC_NonIntrinsic:
+ mismatchIsError = mismatchIsWarning = !isIntrinsic.value_or(false);
+ break;
+ case common::LangOptions::MMC_Warn:
+ mismatchIsError = false;
+ mismatchIsWarning = true;
+ break;
+ }
std::optional<ModuleCheckSumType> checkSum{
VerifyHeader(sourceFile->content())};
if (!checkSum) {
@@ -1758,12 +1773,20 @@ Scope *ModFileReader::Read(SourceName name, std::optional<bool> isIntrinsic,
}
return nullptr;
} else if (requiredHash && *requiredHash != *checkSum) {
- if (!silent) {
- Say("use", name, ancestorName,
- "File is not the right module file for %s"_err_en_US,
- "'"s + name.ToString() + "': "s + sourceFile->path());
+ if (mismatchIsError) {
+ if (!silent) {
+ Say("use", name, ancestorName,
+ "File is not the right module file for %s"_err_en_US,
+ "'"s + name.ToString() + "': "s + sourceFile->path());
+ }
+ return nullptr;
+ } else {
+ if (!silent && mismatchIsWarning) {
+ Warn(name, common::UsageWarning::ModuleFileMismatch, ancestorName,
+ "File has a different checksum than expected for %s"_warn_en_US,
+ "'"s + name.ToString() + "': "s + sourceFile->path());
+ }
}
- return nullptr;
}
llvm::raw_null_ostream NullStream;
parsing.Parse(NullStream, context_.langOptions());
@@ -1893,6 +1916,20 @@ parser::Message &ModFileReader::Say(const char *verb, SourceName name,
parser::MessageFormattedText{std::move(msg), arg}.MoveString());
}
+parser::Message *ModFileReader::Warn(SourceName name,
+ common::UsageWarning warning, const std::string &ancestor,
+ parser::MessageFixedText &&msg, const std::string &arg) {
+ return context_.messages().Warn(/*isInModuleFile=*/false,
+ context_.languageFeatures(), warning, name,
+ "Module file for %s: %s"_warn_en_US,
+ parser::MessageFormattedText{ancestor.empty()
+ ? "module '%s'"_en_US
+ : "submodule '%s' of module '%s'"_en_US,
+ name, ancestor}
+ .MoveString(),
+ parser::MessageFormattedText{std::move(msg), arg}.MoveString());
+}
+
// program was read from a .mod file for a submodule; return the name of the
// submodule's parent submodule, nullptr if none.
static std::optional<SourceName> GetSubmoduleParent(
diff --git a/flang/lib/Semantics/mod-file.h b/flang/lib/Semantics/mod-file.h
index 83834671adac5..2ef012563f610 100644
--- a/flang/lib/Semantics/mod-file.h
+++ b/flang/lib/Semantics/mod-file.h
@@ -109,6 +109,8 @@ class ModFileReader {
parser::Message &Say(const char *verb, SourceName, const std::string &,
parser::MessageFixedText &&, const std::string &);
+ parser::Message *Warn(SourceName, common::UsageWarning, const std::string &,
+ parser::MessageFixedText &&, const std::string &);
};
} // namespace Fortran::semantics
diff --git a/flang/lib/Support/Fortran-features.cpp b/flang/lib/Support/Fortran-features.cpp
index 533db242ac2d3..44e79e636cb16 100644
--- a/flang/lib/Support/Fortran-features.cpp
+++ b/flang/lib/Support/Fortran-features.cpp
@@ -223,6 +223,7 @@ LanguageFeatureControl::LanguageFeatureControl() {
warnUsage_.set(UsageWarning::IgnoredNoReallocateLHS);
warnUsage_.set(UsageWarning::IoImpliedDoIndexConflict);
warnUsage_.set(UsageWarning::BOZLiteralTruncation);
+ warnUsage_.set(UsageWarning::ModuleFileMismatch);
warnLanguage_.set(LanguageFeature::PreferIntrinsicModuleUseAssociation);
warnLanguage_.set(LanguageFeature::OpenMPThreadprivateEquivalence);
warnLanguage_.set(LanguageFeature::OpenAccDefaultNoneScalarsStrict);
diff --git a/flang/test/Semantics/Inputs/dir1/module_mismatch_check_a.mod b/flang/test/Semantics/Inputs/dir1/module_mismatch_check_a.mod
new file mode 100644
index 0000000000000..5690e5bb6775a
--- /dev/null
+++ b/flang/test/Semantics/Inputs/dir1/module_mismatch_check_a.mod
@@ -0,0 +1,6 @@
+!mod$ v1 sum:4fcb3312b6234055
+module module_mismatch_check_a
+contains
+subroutine s1()
+end
+end
diff --git a/flang/test/Semantics/Inputs/dir2/module_mismatch_check_a.mod b/flang/test/Semantics/Inputs/dir2/module_mismatch_check_a.mod
new file mode 100644
index 0000000000000..f2fe3a7e1857d
--- /dev/null
+++ b/flang/test/Semantics/Inputs/dir2/module_mismatch_check_a.mod
@@ -0,0 +1,8 @@
+!mod$ v1 sum:a14ba91f349f847c
+module module_mismatch_check_a
+contains
+subroutine s1()
+end
+subroutine s1a()
+end
+end
diff --git a/flang/test/Semantics/Inputs/module_mismatch_check_b.mod b/flang/test/Semantics/Inputs/module_mismatch_check_b.mod
new file mode 100644
index 0000000000000..1907d34288d59
--- /dev/null
+++ b/flang/test/Semantics/Inputs/module_mismatch_check_b.mod
@@ -0,0 +1,8 @@
+!mod$ v1 sum:f3aa817a771c0caa
+!need$ 4fcb3312b6234055 n module_mismatch_check_a
+module module_mismatch_check_b
+use module_mismatch_check_a,only:s1
+contains
+subroutine s2()
+end
+end
diff --git a/flang/test/Semantics/module-mismatch-check-intrinsic.f90 b/flang/test/Semantics/module-mismatch-check-intrinsic.f90
new file mode 100644
index 0000000000000..bf4f8ff79c30e
--- /dev/null
+++ b/flang/test/Semantics/module-mismatch-check-intrinsic.f90
@@ -0,0 +1,27 @@
+
+! Reject unknown argument option
+! RUN: not %flang -fmodule-mismatch-check=invalid %s 2>&1 | FileCheck --check-prefix=INVALID %s
+! RUN: not %flang_fc1 -fmodule-mismatch-check=invalid %s 2>&1 | FileCheck --check-prefix=INVALID %s
+! INVALID: error: invalid value 'invalid' in '-fmodule-mismatch-check=invalid'
+
+
+! Test module dependency checksum mismatch handling for intrinsic modules
+! Inputs/device-side-modules-a.mod records a deliberately wrong checksum for
+! its dependency on iso_fortran_env.
+! DEFINE: %{checksum_mismatch} = -fsyntax-only -I%S/Inputs
+
+! RUN: not %flang_fc1 %{checksum_mismatch} %s 2>&1 | FileCheck --check-prefix=REJECT %s
+! RUN: not %flang_fc1 %{checksum_mismatch} -fmodule-mismatch-check=on %s 2>&1 | FileCheck --check-prefix=REJECT %s
+! REJECT: Cannot use module file for module 'iso_fortran_env': File is not the right module file for 'iso_fortran_env'
+
+! RUN: %flang %{checksum_mismatch} -fmodule-mismatch-check=warn %s 2>&1 | FileCheck --check-prefix=WARNING %s
+! WARNING: warning: Module file for module 'iso_fortran_env': File has a different checksum than expected for 'iso_fortran_env':
+
+! RUN: %flang %{checksum_mismatch} -fmodule-mismatch-check=non-intrinsic %s 2>&1 | FileCheck --allow-empty --check-prefix=NO-WARN %s
+! RUN: %flang %{checksum_mismatch} -fmodule-mismatch-check=warn -Wno-module-file-mismatch %s 2>&1 | FileCheck --allow-empty --check-prefix=NO-WARN %s
+! NO-WARN-NOT: warning
+
+
+module module_mismatch_check_intrinsic
+ use device_modfile01_a, only: x
+end module
diff --git a/flang/test/Semantics/module-mismatch-check-user.f90 b/flang/test/Semantics/module-mismatch-check-user.f90
new file mode 100644
index 0000000000000..f1d7f893dd6b2
--- /dev/null
+++ b/flang/test/Semantics/module-mismatch-check-user.f90
@@ -0,0 +1,32 @@
+
+! Reject unknown argument option
+! RUN: not %flang -fmodule-mismatch-check=invalid %s 2>&1 | FileCheck --check-prefix=INVALID %s
+! RUN: not %flang_fc1 -fmodule-mismatch-check=invalid %s 2>&1 | FileCheck --check-prefix=INVALID %s
+! INVALID: error: invalid value 'invalid' in '-fmodule-mismatch-check=invalid'
+
+
+! Test module dependency checksum mismatch handling for user modules
+! DEFINE: %{checksum_correct} = -fsyntax-only -I%S/Inputs -I%S/Inputs/dir1
+! DEFINE: %{checksum_mismatch} = -fsyntax-only -I%S/Inputs -I%S/Inputs/dir2
+
+! Correct checksum in Inputs/dir1
+! RUN: %flang_fc1 %{checksum_correct} %s
+
+! Invalid checksum in Inputs/dir2
+! RUN: not %flang_fc1 %{checksum_mismatch} %s 2>&1 | FileCheck --check-prefix=REJECT %s
+! RUN: not %flang_fc1 %{checksum_mismatch} -fmodule-mismatch-check=on %s 2>&1 | FileCheck --check-prefix=REJECT %s
+! RUN: not %flang_fc1 %{checksum_mismatch} -fmodule-mismatch-check=non-intrinsic %s 2>&1 | FileCheck --check-prefix=REJECT %s
+! REJECT: Cannot use module file for module 'module_mismatch_check_a': File is not the right module file for 'module_mismatch_check_a':
+
+! Convert checksum mismatch to warning
+! RUN: %flang %{checksum_mismatch} -fmodule-mismatch-check=warn %s 2>&1 | FileCheck --check-prefix=WARNING %s
+! WARNING: warning: Module file for module 'module_mismatch_check_a': File has a different checksum than expected for 'module_mismatch_check_a':
+
+! Silence warning using option
+! RUN: %flang %{checksum_mismatch} -fmodule-mismatch-check=warn -Wno-module-file-mismatch %s 2>&1 | FileCheck --allow-empty --check-prefix=NO-WARNING %s
+! NO-WARNING-NOT: warning
+
+
+use module_mismatch_check_b
+call s2
+end
>From 7340933e1e308789073a4bd9bcaa323d9d668b64 Mon Sep 17 00:00:00 2001
From: Michael Kruse <llvm-project at meinersbur.de>
Date: Thu, 27 Aug 2026 10:20:03 +0200
Subject: [PATCH 2/2] Consider files in -fintrinsic-modules-path as intrinsics
unless overridden
---
clang/include/clang/Options/FlangOptions.td | 14 ++++++++--
flang/docs/ReleaseNotes.md | 5 ++++
flang/lib/Semantics/mod-file.cpp | 28 +++++++++----------
.../Semantics/Inputs/device_modfile01_b.mod | 6 ++++
...ule-mismatch-check-intrinsic-explicit.f90} | 7 +++--
...dule-mismatch-check-intrinsic-implicit.f90 | 28 +++++++++++++++++++
6 files changed, 68 insertions(+), 20 deletions(-)
create mode 100644 flang/test/Semantics/Inputs/device_modfile01_b.mod
rename flang/test/Semantics/{module-mismatch-check-intrinsic.f90 => module-mismatch-check-intrinsic-explicit.f90} (76%)
create mode 100644 flang/test/Semantics/module-mismatch-check-intrinsic-implicit.f90
diff --git a/clang/include/clang/Options/FlangOptions.td b/clang/include/clang/Options/FlangOptions.td
index 980508ba98947..47f707b0003cc 100644
--- a/clang/include/clang/Options/FlangOptions.td
+++ b/clang/include/clang/Options/FlangOptions.td
@@ -137,8 +137,18 @@ def module_dir : JoinedOrSeparate<["-"], "module-dir">, MetaVarName<"<dir>">,
DocBrief<[{This option specifies where to put .mod files for compiled modules.
It is also added to the list of directories to be searched by an USE statement.
The default is the current directory.}]>;
-def fmodule_mismatch_check_EQ : Joined<["-"], "fmodule-mismatch-check=">, Group<f_Group>,
- HelpText<"Check consistency of used modules (option: on, non-intrinsic, warn)">;
+def fmodule_mismatch_check_EQ : Joined<["-"], "fmodule-mismatch-check=">,
+ Group<f_Group>,
+ HelpText<"Check consistency of used modules (option: on, non-intrinsic, warn)">,
+ DocBrief<[{Normally, when loading a .mod file, Flang checks whether the
+modules it itself depends on are the same modules from when the .mod file was
+created. If there is a mismatch, compilation fails. The option converts this
+error into a warning instead. The warning can be silenced using
+-Wno-module-file-mismatch and thus mismatches are completely ignored.
+-fmodule-mismatch-check=non-intrinsic still keeps the error for user modules
+where mismatches hint towards a build dependency problem. Mismatches of
+intrinsic modules are expected after a compiler upgrade. Upgraded intrinsic
+modules are supposed to be backwards-compatible.}]>;
def ffixed_form : Flag<["-"], "ffixed-form">, Group<f_Group>,
HelpText<"Process source files in fixed form">;
diff --git a/flang/docs/ReleaseNotes.md b/flang/docs/ReleaseNotes.md
index bbc7084c4a757..5150854be051d 100644
--- a/flang/docs/ReleaseNotes.md
+++ b/flang/docs/ReleaseNotes.md
@@ -57,6 +57,11 @@ page](https://llvm.org/releases/).
- Added `-gz` and `-gz=<format>` flags to enable compression of DWARF debug
sections. Supported formats are `zlib`, `zstd`, and `none`.
+- Added `-fmodule-mismatch-check=non-intrinsic` and
+ `-fmodule-mismatch-check=warn` to turn module USE checksum mismatches into a
+ warning instead of an error. `-Wno-module-file-mismatch` can be used to
+ silence even that warning.
+
## Windows Support
## Fortran Language Changes in Flang
diff --git a/flang/lib/Semantics/mod-file.cpp b/flang/lib/Semantics/mod-file.cpp
index 5e9b1d1da00b1..d0df304910422 100644
--- a/flang/lib/Semantics/mod-file.cpp
+++ b/flang/lib/Semantics/mod-file.cpp
@@ -1745,18 +1745,25 @@ Scope *ModFileReader::Read(SourceName name, std::optional<bool> isIntrinsic,
}
CHECK(sourceFile);
- bool mismatchIsError, mismatchIsWarning;
+ if (!isIntrinsic.has_value()) {
+ for (const auto &dir : context_.intrinsicModuleDirectories()) {
+ if (sourceFile->path().size() > dir.size() &&
+ sourceFile->path().find(dir) == 0) {
+ isIntrinsic = true;
+ break;
+ }
+ }
+ }
+ bool mismatchIsError;
switch (context_.langOptions().getModuleMismatchCheck()) {
case common::LangOptions::MMC_On:
mismatchIsError = true;
- mismatchIsWarning = true;
break;
case common::LangOptions::MMC_NonIntrinsic:
- mismatchIsError = mismatchIsWarning = !isIntrinsic.value_or(false);
+ mismatchIsError = !isIntrinsic.value_or(false);
break;
case common::LangOptions::MMC_Warn:
mismatchIsError = false;
- mismatchIsWarning = true;
break;
}
std::optional<ModuleCheckSumType> checkSum{
@@ -1776,12 +1783,12 @@ Scope *ModFileReader::Read(SourceName name, std::optional<bool> isIntrinsic,
if (mismatchIsError) {
if (!silent) {
Say("use", name, ancestorName,
- "File is not the right module file for %s"_err_en_US,
+ "File is not the right module file for %s. Use -fmodule-mismatch-check=warn to turn this error into a warning."_err_en_US,
"'"s + name.ToString() + "': "s + sourceFile->path());
}
return nullptr;
} else {
- if (!silent && mismatchIsWarning) {
+ if (!silent) {
Warn(name, common::UsageWarning::ModuleFileMismatch, ancestorName,
"File has a different checksum than expected for %s"_warn_en_US,
"'"s + name.ToString() + "': "s + sourceFile->path());
@@ -1801,15 +1808,6 @@ Scope *ModFileReader::Read(SourceName name, std::optional<bool> isIntrinsic,
}
parser::Program &parseTree{context_.SaveParseTree(std::move(*parsedProgram))};
Scope *parentScope; // the scope this module/submodule goes into
- if (!isIntrinsic.has_value()) {
- for (const auto &dir : context_.intrinsicModuleDirectories()) {
- if (sourceFile->path().size() > dir.size() &&
- sourceFile->path().find(dir) == 0) {
- isIntrinsic = true;
- break;
- }
- }
- }
Scope &topScope{isIntrinsic.value_or(false) ? context_.intrinsicModulesScope()
: context_.globalScope()};
Symbol *moduleSymbol{nullptr};
diff --git a/flang/test/Semantics/Inputs/device_modfile01_b.mod b/flang/test/Semantics/Inputs/device_modfile01_b.mod
new file mode 100644
index 0000000000000..4253c7122b20d
--- /dev/null
+++ b/flang/test/Semantics/Inputs/device_modfile01_b.mod
@@ -0,0 +1,6 @@
+!mod$ v1 sum:2280842c8e8a5ea7
+!need$ 0000000000000000 i iso_fortran_env
+module device_modfile01_b
+use::iso_fortran_env,only:int32
+integer(4)::x
+end
diff --git a/flang/test/Semantics/module-mismatch-check-intrinsic.f90 b/flang/test/Semantics/module-mismatch-check-intrinsic-explicit.f90
similarity index 76%
rename from flang/test/Semantics/module-mismatch-check-intrinsic.f90
rename to flang/test/Semantics/module-mismatch-check-intrinsic-explicit.f90
index bf4f8ff79c30e..dfbaa97077bc7 100644
--- a/flang/test/Semantics/module-mismatch-check-intrinsic.f90
+++ b/flang/test/Semantics/module-mismatch-check-intrinsic-explicit.f90
@@ -14,10 +14,11 @@
! RUN: not %flang_fc1 %{checksum_mismatch} -fmodule-mismatch-check=on %s 2>&1 | FileCheck --check-prefix=REJECT %s
! REJECT: Cannot use module file for module 'iso_fortran_env': File is not the right module file for 'iso_fortran_env'
-! RUN: %flang %{checksum_mismatch} -fmodule-mismatch-check=warn %s 2>&1 | FileCheck --check-prefix=WARNING %s
-! WARNING: warning: Module file for module 'iso_fortran_env': File has a different checksum than expected for 'iso_fortran_env':
+! RUN: %flang %{checksum_mismatch} -fmodule-mismatch-check=non-intrinsic %s 2>&1 | FileCheck --allow-empty --check-prefix=WARN %s
+! RUN: %flang %{checksum_mismatch} -fmodule-mismatch-check=warn %s 2>&1 | FileCheck --check-prefix=WARN %s
+! WARN: warning: Module file for module 'iso_fortran_env': File has a different checksum than expected for 'iso_fortran_env':
-! RUN: %flang %{checksum_mismatch} -fmodule-mismatch-check=non-intrinsic %s 2>&1 | FileCheck --allow-empty --check-prefix=NO-WARN %s
+! RUN: %flang %{checksum_mismatch} -fmodule-mismatch-check=non-intrinsic -Wno-module-file-mismatch %s 2>&1 | FileCheck --allow-empty --check-prefix=NO-WARN %s
! RUN: %flang %{checksum_mismatch} -fmodule-mismatch-check=warn -Wno-module-file-mismatch %s 2>&1 | FileCheck --allow-empty --check-prefix=NO-WARN %s
! NO-WARN-NOT: warning
diff --git a/flang/test/Semantics/module-mismatch-check-intrinsic-implicit.f90 b/flang/test/Semantics/module-mismatch-check-intrinsic-implicit.f90
new file mode 100644
index 0000000000000..5031a8bdf845d
--- /dev/null
+++ b/flang/test/Semantics/module-mismatch-check-intrinsic-implicit.f90
@@ -0,0 +1,28 @@
+
+! Reject unknown argument option
+! RUN: not %flang -fmodule-mismatch-check=invalid %s 2>&1 | FileCheck --check-prefix=INVALID %s
+! RUN: not %flang_fc1 -fmodule-mismatch-check=invalid %s 2>&1 | FileCheck --check-prefix=INVALID %s
+! INVALID: error: invalid value 'invalid' in '-fmodule-mismatch-check=invalid'
+
+
+! Test module dependency checksum mismatch handling for intrinsic modules
+! Inputs/device-side-modules-a.mod records a deliberately wrong checksum for
+! its dependency on iso_fortran_env.
+! DEFINE: %{checksum_mismatch} = -fsyntax-only -I%S/Inputs
+
+! RUN: not %flang_fc1 %{checksum_mismatch} %s 2>&1 | FileCheck --check-prefix=REJECT %s
+! RUN: not %flang_fc1 %{checksum_mismatch} -fmodule-mismatch-check=on %s 2>&1 | FileCheck --check-prefix=REJECT %s
+! REJECT: Cannot use module file for module 'iso_fortran_env': File is not the right module file for 'iso_fortran_env'
+
+! RUN: %flang %{checksum_mismatch} -fmodule-mismatch-check=non-intrinsic %s 2>&1 | FileCheck --allow-empty --check-prefix=WARN %s
+! RUN: %flang %{checksum_mismatch} -fmodule-mismatch-check=warn %s 2>&1 | FileCheck --check-prefix=WARN %s
+! WARN: warning: Module file for module 'iso_fortran_env': File has a different checksum than expected for 'iso_fortran_env':
+
+! RUN: %flang %{checksum_mismatch} -fmodule-mismatch-check=non-intrinsic -Wno-module-file-mismatch %s 2>&1 | FileCheck --allow-empty --check-prefix=NO-WARN %s
+! RUN: %flang %{checksum_mismatch} -fmodule-mismatch-check=warn -Wno-module-file-mismatch %s 2>&1 | FileCheck --allow-empty --check-prefix=NO-WARN %s
+! NO-WARN-NOT: warning
+
+
+module module_mismatch_check_intrinsic
+ use device_modfile01_b, only: x
+end module
More information about the flang-commits
mailing list