[flang-commits] [flang] [flang][Semantics] Introduce `-Wpass-global-variable` warning (PR #160324)
via flang-commits
flang-commits at lists.llvm.org
Tue Sep 23 08:17:36 PDT 2025
https://github.com/foxtran created https://github.com/llvm/llvm-project/pull/160324
In this PR, I've implemented detection of passing global variables defined in common blocks or/and modules in a bit naive way.
The main reason of implementing this that we have a lot of bugs with ifx compiler due extensively usage of passing all possible variables from common blocks to subroutines.
Sometimes, Fortran programs actively utilises passing of global variables in a valid context, especially for stack memory allocators (like in GAMESS(US) or MRCC or Gaussian). For such cases, I've excluded those warning:
- common block has only one variable of shape [ 1 ]
- variable of shape [ 1 ] in module has attribute `allocatable`, `pointer` or `volatile`
- variable in module has attribute `parameter`
See allowed cases in test.
However, PR still have bugs.
- the checks are still working in compile time expressions (for example `flang/test/Evaluate/fold-type.f90`)
- by some reason, `!$omp declare target enter (val)` is supposed to be a function, so, the warnings are shown in this context
- the warning happens in already written tests
>From 19bb9f26ae81fa09751e4a091f7483d022a73577 Mon Sep 17 00:00:00 2001
From: "Igor S. Gerasimov" <foxtranigor at gmail.com>
Date: Tue, 23 Sep 2025 16:20:05 +0200
Subject: [PATCH 1/5] Implement -Wpass-global-variable flag for flang
---
flang/include/flang/Support/Fortran-features.h | 2 +-
flang/lib/Support/Fortran-features.cpp | 1 +
flang/unittests/Common/FortranFeaturesTest.cpp | 3 +++
3 files changed, 5 insertions(+), 1 deletion(-)
diff --git a/flang/include/flang/Support/Fortran-features.h b/flang/include/flang/Support/Fortran-features.h
index 2bbc2385777da..78bec21748405 100644
--- a/flang/include/flang/Support/Fortran-features.h
+++ b/flang/include/flang/Support/Fortran-features.h
@@ -79,7 +79,7 @@ ENUM_CLASS(UsageWarning, Portability, PointerToUndefinable,
CompatibleDeclarationsFromDistinctModules,
NullActualForDefaultIntentAllocatable, UseAssociationIntoSameNameSubprogram,
HostAssociatedIntentOutInSpecExpr, NonVolatilePointerToVolatile,
- RealConstantWidening, VolatileOrAsynchronousTemporary)
+ RealConstantWidening, VolatileOrAsynchronousTemporary, PassGlobalVariable)
using LanguageFeatures = EnumSet<LanguageFeature, LanguageFeature_enumSize>;
using UsageWarnings = EnumSet<UsageWarning, UsageWarning_enumSize>;
diff --git a/flang/lib/Support/Fortran-features.cpp b/flang/lib/Support/Fortran-features.cpp
index 4a6fb8d75a135..bb5c7b56634e8 100644
--- a/flang/lib/Support/Fortran-features.cpp
+++ b/flang/lib/Support/Fortran-features.cpp
@@ -149,6 +149,7 @@ LanguageFeatureControl::LanguageFeatureControl() {
warnUsage_.set(UsageWarning::HostAssociatedIntentOutInSpecExpr);
warnUsage_.set(UsageWarning::NonVolatilePointerToVolatile);
warnUsage_.set(UsageWarning::RealConstantWidening);
+ warnUsage_.set(UsageWarning::PassGlobalVariable);
// New warnings, on by default
warnLanguage_.set(LanguageFeature::SavedLocalInSpecExpr);
warnLanguage_.set(LanguageFeature::NullActualForAllocatable);
diff --git a/flang/unittests/Common/FortranFeaturesTest.cpp b/flang/unittests/Common/FortranFeaturesTest.cpp
index 9408da0361e1d..80417cfae035d 100644
--- a/flang/unittests/Common/FortranFeaturesTest.cpp
+++ b/flang/unittests/Common/FortranFeaturesTest.cpp
@@ -556,6 +556,9 @@ TEST(FortranFeaturesTest, CamelCaseToLowerCaseHyphenated) {
EXPECT_EQ(CamelCaseToLowerCaseHyphenated(
EnumToString(UsageWarning::NonVolatilePointerToVolatile)),
"non-volatile-pointer-to-volatile");
+ EXPECT_EQ(
+ CamelCaseToLowerCaseHyphenated(EnumToString(UsageWarning::PassGlobalVariable)),
+ "pass-global-variable");
}
TEST(FortranFeaturesTest, HintLanguageControlFlag) {
>From 0daa60d8566dcc8dc9db69b184d40997a1c38f73 Mon Sep 17 00:00:00 2001
From: "Igor S. Gerasimov" <foxtranigor at gmail.com>
Date: Tue, 23 Sep 2025 16:28:52 +0200
Subject: [PATCH 2/5] Add test for -Wpass-global-variable
---
.../test/Semantics/pass-global-variables.f90 | 169 ++++++++++++++++++
1 file changed, 169 insertions(+)
create mode 100644 flang/test/Semantics/pass-global-variables.f90
diff --git a/flang/test/Semantics/pass-global-variables.f90 b/flang/test/Semantics/pass-global-variables.f90
new file mode 100644
index 0000000000000..73d1b8e334180
--- /dev/null
+++ b/flang/test/Semantics/pass-global-variables.f90
@@ -0,0 +1,169 @@
+!RUN: %python %S/test_errors.py %s %flang_fc1 -Werror
+module explicit_test_mod
+ implicit none (type, external)
+ integer :: i1
+ integer :: i2(1)
+ integer :: i3(3)
+ integer, allocatable :: ia(:)
+
+ real :: x1, y1
+ real :: x2, y2
+ real :: z, z2
+ common /xy1/ x1, y1(1)
+ common /xy2/ x2(1), y2
+ common /fm/ z(1)
+ common /fm_bad/ z2(5)
+contains
+ subroutine pass_int(i)
+ integer, intent(inout) :: i
+ end subroutine pass_int
+ subroutine pass_int_1d(i)
+ integer, intent(inout) :: i(*)
+ end subroutine pass_int_1d
+ subroutine pass_real(r)
+ real, intent(inout) :: r
+ end subroutine pass_real
+ subroutine pass_real_1d(r)
+ real, intent(inout) :: r(*)
+ end subroutine pass_real_1d
+ subroutine explicit_test(n)
+ integer, intent(in) :: n
+
+ !WARNING: Passing global variable 'i1' from MODULE 'explicit_test_mod' as function argument [-Wpass-global-variable]
+ call pass_int(i1) !< warn: basic type
+ call pass_int(i2(1)) !< ok: shape == [1]
+ call pass_int(i2(n)) !< ok: shape == [1]
+ !WARNING: Passing global variable 'i3' from MODULE 'explicit_test_mod' as function argument [-Wpass-global-variable]
+ call pass_int(i3(1)) !< warn: shape /= [1]
+ !WARNING: Passing global variable 'i3' from MODULE 'explicit_test_mod' as function argument [-Wpass-global-variable]
+ call pass_int(i3(n)) !< warn: shape /= [1]
+ !WARNING: Passing global variable 'i2' from MODULE 'explicit_test_mod' as function argument [-Wpass-global-variable]
+ call pass_int_1d(i2) !< warn: whole array is passed
+ call pass_int_1d(i2(n:n+3)) !< ok: subrange of array
+ !WARNING: Passing global variable 'i3' from MODULE 'explicit_test_mod' as function argument [-Wpass-global-variable]
+ call pass_int_1d(i3) !< warn: shape /= [1]
+ !WARNING: Passing global variable 'i3' from MODULE 'explicit_test_mod' as function argument [-Wpass-global-variable]
+ call pass_int_1d(i3(n:n+3)) !< warn: shape /= [1]
+ call pass_int(ia(1)) !< ok: allocatable
+ call pass_int(ia(n)) !< ok: allocatable
+ call pass_int_1d(ia) !< ok: allocatable
+ call pass_int_1d(ia(n:n+3)) !< ok: allocatable
+
+ !WARNING: Passing global variable 'x1' from COMMON 'xy1' as function argument [-Wpass-global-variable]
+ call pass_real(x1) !< warn: x1 from common
+ !WARNING: Passing global variable 'y1' from COMMON 'xy1' as function argument [-Wpass-global-variable]
+ call pass_real_1d(y1) !< warn: y1 from common or offset /= 0
+ !WARNING: Passing global variable 'y1' from COMMON 'xy1' as function argument [-Wpass-global-variable]
+ call pass_real(y1(1)) !< warn: offset /= 0
+ !WARNING: Passing global variable 'y1' from COMMON 'xy1' as function argument [-Wpass-global-variable]
+ call pass_real(y1(n)) !< warn: offset /= 0
+ !WARNING: Passing global variable 'y1' from COMMON 'xy1' as function argument [-Wpass-global-variable]
+ call pass_real_1d(y1(n:n+3)) !< warn: offset /= 0
+
+ !WARNING: Passing global variable 'y2' from COMMON 'xy2' as function argument [-Wpass-global-variable]
+ call pass_real(y2) !< warn: offset /= 0
+ !WARNING: Passing global variable 'x2' from COMMON 'xy2' as function argument [-Wpass-global-variable]
+ call pass_real_1d(x2) !< warn: more than one variable in common block
+ !WARNING: Passing global variable 'x2' from COMMON 'xy2' as function argument [-Wpass-global-variable]
+ call pass_real(x2(1)) !< warn: more than one variable in common block
+ !WARNING: Passing global variable 'x2' from COMMON 'xy2' as function argument [-Wpass-global-variable]
+ call pass_real(x2(n)) !< warn: more than one variable in common block
+ !WARNING: Passing global variable 'x2' from COMMON 'xy2' as function argument [-Wpass-global-variable]
+ call pass_real_1d(x2(n:n+3)) !< warn: more than one variable in common block
+
+ !WARNING: Passing global variable 'z' from COMMON 'fm' as function argument [-Wpass-global-variable]
+ call pass_real_1d(z) !< warn: z from common
+ call pass_real(z(1)) !< ok: single element/begin of mem block
+ call pass_real(z(n)) !< ok: single element/begin of mem block
+ call pass_real_1d(z(n:n+3)) !< ok: mem block
+
+ !WARNING: Passing global variable 'z2' from COMMON 'fm_bad' as function argument [-Wpass-global-variable]
+ call pass_real_1d(z2) !< warn: shape /= [1]
+ !WARNING: Passing global variable 'z2' from COMMON 'fm_bad' as function argument [-Wpass-global-variable]
+ call pass_real(z2(1)) !< warn: shape /= [1]
+ !WARNING: Passing global variable 'z2' from COMMON 'fm_bad' as function argument [-Wpass-global-variable]
+ call pass_real(z2(n)) !< warn: shape /= [1]
+ !WARNING: Passing global variable 'z2' from COMMON 'fm_bad' as function argument [-Wpass-global-variable]
+ call pass_real_1d(z2(n:n+3)) !< warn: shape /= [1]
+ end subroutine explicit_test
+end module explicit_test_mod
+
+subroutine module_test(n)
+ use explicit_test_mod, only: i1, i2, i3, ia
+ implicit none (type, external)
+ integer, intent(in) :: n
+
+ external :: imp_pass_int, imp_pass_int_1d
+
+ !WARNING: Passing global variable 'i1' from MODULE 'explicit_test_mod' as function argument [-Wpass-global-variable]
+ call imp_pass_int(i1) !< warn: i1 from common
+ call imp_pass_int(i2(1)) !< ok: single element/begin of mem block
+ call imp_pass_int(i2(n)) !< ok: single element/begin of mem block
+ !WARNING: Passing global variable 'i3' from MODULE 'explicit_test_mod' as function argument [-Wpass-global-variable]
+ call imp_pass_int(i3(1)) !< warn: shape /= [1]
+ !WARNING: Passing global variable 'i3' from MODULE 'explicit_test_mod' as function argument [-Wpass-global-variable]
+ call imp_pass_int(i3(n)) !< warn: shape /= [1]
+ call imp_pass_int(ia(1)) !< ok: allocatable
+ call imp_pass_int(ia(n)) !< ok: allocatable
+
+ !WARNING: Passing global variable 'i2' from MODULE 'explicit_test_mod' as function argument [-Wpass-global-variable]
+ call imp_pass_int_1d(i2) !< warn: i2 from module
+ call imp_pass_int_1d(i2(n:n+3)) !< ok: mem block
+ !WARNING: Passing global variable 'i3' from MODULE 'explicit_test_mod' as function argument [-Wpass-global-variable]
+ call imp_pass_int_1d(i3) !< warn: i3 from module & shape /= [1]
+ !WARNING: Passing global variable 'i3' from MODULE 'explicit_test_mod' as function argument [-Wpass-global-variable]
+ call imp_pass_int_1d(i3(n:n+3)) !< warn: shape /= [1]
+ call imp_pass_int_1d(ia) !< ok: allocatable
+ call imp_pass_int_1d(ia(n:n+3)) !< ok: allocatable
+end subroutine module_test
+
+subroutine implicit_test(n)
+ implicit none (type, external)
+ integer, intent(in) :: n
+ real :: x1, y1
+ real :: x2, y2
+ real :: z, z2
+ common /xy1/ x1, y1(1)
+ common /xy2/ x2(1), y2
+ common /fm/ z(1)
+ common /fm_bad/ z2(5)
+
+ external :: imp_pass_real, imp_pass_real_1d
+
+ !WARNING: Passing global variable 'x1' from COMMON 'xy1' as function argument [-Wpass-global-variable]
+ call imp_pass_real(x1) !< warn: x1 from common
+ !WARNING: Passing global variable 'y1' from COMMON 'xy1' as function argument [-Wpass-global-variable]
+ call imp_pass_real_1d(y1) !< warn: y1 from common and offset /= 0
+ !WARNING: Passing global variable 'y1' from COMMON 'xy1' as function argument [-Wpass-global-variable]
+ call imp_pass_real(y1(1)) !< warn: offset /= 0
+ !WARNING: Passing global variable 'y1' from COMMON 'xy1' as function argument [-Wpass-global-variable]
+ call imp_pass_real(y1(n)) !< warn: offset /= 0
+ !WARNING: Passing global variable 'y1' from COMMON 'xy1' as function argument [-Wpass-global-variable]
+ call imp_pass_real_1d(y1(n:n+3)) !< warn: offset /= 0
+
+ !WARNING: Passing global variable 'y2' from COMMON 'xy2' as function argument [-Wpass-global-variable]
+ call imp_pass_real(y2) !< warn: y2 from common and offset /= 0
+ !WARNING: Passing global variable 'x2' from COMMON 'xy2' as function argument [-Wpass-global-variable]
+ call imp_pass_real_1d(x2) !< warn: x2 from common
+ !WARNING: Passing global variable 'x2' from COMMON 'xy2' as function argument [-Wpass-global-variable]
+ call imp_pass_real(x2(1)) !< warn: more than one variable in common
+ !WARNING: Passing global variable 'x2' from COMMON 'xy2' as function argument [-Wpass-global-variable]
+ call imp_pass_real(x2(n)) !< warn: more than one variable in common
+ !WARNING: Passing global variable 'x2' from COMMON 'xy2' as function argument [-Wpass-global-variable]
+ call imp_pass_real_1d(x2(n:n+3)) !< warn: more than one variable in common
+
+ !WARNING: Passing global variable 'z' from COMMON 'fm' as function argument [-Wpass-global-variable]
+ call imp_pass_real_1d(z) !< warn: z from common
+ call imp_pass_real(z(1)) !< ok: single element/begin of mem block
+ call imp_pass_real(z(n)) !< ok: single element/begin of mem block
+ call imp_pass_real_1d(z(n:n+3)) !< ok: mem block
+
+ !WARNING: Passing global variable 'z2' from COMMON 'fm_bad' as function argument [-Wpass-global-variable]
+ call imp_pass_real_1d(z2) !< warn: z2 from common, shape /= [1]
+ !WARNING: Passing global variable 'z2' from COMMON 'fm_bad' as function argument [-Wpass-global-variable]
+ call imp_pass_real(z2(1)) !< warn: shape /= [1]
+ !WARNING: Passing global variable 'z2' from COMMON 'fm_bad' as function argument [-Wpass-global-variable]
+ call imp_pass_real(z2(n)) !< warn: shape /= [1]
+ !WARNING: Passing global variable 'z2' from COMMON 'fm_bad' as function argument [-Wpass-global-variable]
+ call imp_pass_real_1d(z2(n:n+3)) !< warn: shape /= [1]
+end subroutine implicit_test
>From d53f48bd4808d021e753fbc435f00aeedb66c752 Mon Sep 17 00:00:00 2001
From: "Igor S. Gerasimov" <foxtranigor at gmail.com>
Date: Tue, 23 Sep 2025 16:45:29 +0200
Subject: [PATCH 3/5] Full implementation of -Wpass-global-varialbe for
explicit interfaces
---
flang/lib/Semantics/check-call.cpp | 57 ++++++++++++++++++++++++++++++
1 file changed, 57 insertions(+)
diff --git a/flang/lib/Semantics/check-call.cpp b/flang/lib/Semantics/check-call.cpp
index 797fd067b8185..e259db4f23a18 100644
--- a/flang/lib/Semantics/check-call.cpp
+++ b/flang/lib/Semantics/check-call.cpp
@@ -1137,6 +1137,63 @@ static void CheckExplicitDataArg(const characteristics::DummyDataObject &dummy,
messages.Say(
"%VAL argument must be a scalar numeric or logical expression"_err_en_US);
}
+
+ // passing global variables
+ if (actualFirstSymbol) {
+ bool warn{false};
+ std::string ownerType{""};
+ std::string ownerName{""};
+ if (actualFirstSymbol->flags().test(Symbol::Flag::InCommonBlock)) {
+ const Symbol *common{FindCommonBlockContaining(*actualFirstSymbol)};
+ ownerType = "COMMON";
+ ownerName = common->name().ToString();
+ if (!(actualFirstSymbol->Rank() == 1 && actualFirstSymbol->offset() == 0)) {
+ warn |= true;
+ } else if (actualFirstSymbol->Rank() == 1) {
+ bool actualIsArrayElement{IsArrayElement(actual) != nullptr};
+ if (!actualIsArrayElement) {
+ warn |= true;
+ }
+ if (const ArraySpec *dims{actualFirstSymbol->GetShape()};
+ dims && dims->IsExplicitShape()) {
+ if (!((*dims)[0].lbound().GetExplicit() == (*dims)[0].ubound().GetExplicit())) {
+ warn |= true;
+ }
+ }
+ if (common->get<CommonBlockDetails>().objects().size() > 1) {
+ warn |= true;
+ }
+ }
+ } else if (const auto &owner{actualFirstSymbol->GetUltimate().owner()};
+ owner.IsModule() || owner.IsSubmodule()) {
+ const Scope *module{FindModuleContaining(owner)};
+ ownerType = "MODULE";
+ ownerName = module->GetName()->ToString();
+ if (actualFirstSymbol->attrs().test(Attr::PARAMETER)) {
+ warn |= false;
+ } else if (actualFirstSymbol->Rank() != 1) {
+ warn |= true;
+ } else if (!actualFirstSymbol->attrs().test(Attr::ALLOCATABLE) &&
+ !actualFirstSymbol->attrs().test(Attr::POINTER) &&
+ !actualFirstSymbol->attrs().test(Attr::VOLATILE)) {
+ bool actualIsArrayElement{IsArrayElement(actual) != nullptr};
+ if (!actualIsArrayElement) {
+ warn |= true;
+ }
+ if (const ArraySpec *dims{actualFirstSymbol->GetShape()};
+ dims && dims->IsExplicitShape()) {
+ if (!((*dims)[0].lbound().GetExplicit() == (*dims)[0].ubound().GetExplicit())) {
+ warn |= true;
+ }
+ }
+ }
+ }
+ if (warn) {
+ context.Warn(common::UsageWarning::PassGlobalVariable, messages.at(),
+ "Passing global variable '%s' from %s '%s' as function argument"_warn_en_US,
+ actualFirstSymbol->name(), ownerType, ownerName);
+ }
+ }
}
static void CheckProcedureArg(evaluate::ActualArgument &arg,
>From 947180e64283f43ae24d6593b6fb3cc281f2c9d5 Mon Sep 17 00:00:00 2001
From: "Igor S. Gerasimov" <foxtranigor at gmail.com>
Date: Tue, 23 Sep 2025 16:45:56 +0200
Subject: [PATCH 4/5] Implementation of -Wpass-global-variable for implicit
interfaces
---
flang/lib/Semantics/check-call.cpp | 91 +++++++++++++++++++++++++++++-
1 file changed, 88 insertions(+), 3 deletions(-)
diff --git a/flang/lib/Semantics/check-call.cpp b/flang/lib/Semantics/check-call.cpp
index e259db4f23a18..1b8f914fc1e85 100644
--- a/flang/lib/Semantics/check-call.cpp
+++ b/flang/lib/Semantics/check-call.cpp
@@ -56,9 +56,64 @@ static void CheckImplicitInterfaceArg(evaluate::ActualArgument &arg,
"%VAL argument must be a scalar numeric or logical expression"_err_en_US);
}
if (const auto *expr{arg.UnwrapExpr()}) {
- if (const Symbol * base{GetFirstSymbol(*expr)};
- base && IsFunctionResult(*base)) {
- context.NoteDefinedSymbol(*base);
+ if (const Symbol * base{GetFirstSymbol(*expr)}) {
+ if (IsFunctionResult(*base)) {
+ context.NoteDefinedSymbol(*base);
+ } else {
+ // passing global variables
+ // here, arrays with subscripts are processing
+ bool warn{false};
+ std::string ownerName{""};
+ std::string ownerType{""};
+ if (base->flags().test(Symbol::Flag::InCommonBlock)) {
+ const Symbol *common{FindCommonBlockContaining(*base)};
+ ownerType = "COMMON";
+ ownerName = common->name().ToString();
+ if (!(base->Rank() == 1 && base->offset() == 0)) {
+ warn |= true;
+ } else if (base->Rank() == 1) {
+ if (const ArraySpec *dims{base->GetShape()};
+ dims && dims->IsExplicitShape()) {
+ if (!((*dims)[0].lbound().GetExplicit() == (*dims)[0].ubound().GetExplicit())) {
+ warn |= true;
+ }
+ }
+ if (common->get<CommonBlockDetails>().objects().size() > 1) {
+ warn |= true;
+ }
+ }
+ } else if (const auto &owner{base->GetUltimate().owner()};
+ owner.IsModule() || owner.IsSubmodule()) {
+ const Scope *module{FindModuleContaining(owner)};
+ ownerType = "MODULE";
+ ownerName = module->GetName()->ToString();
+ if (base->attrs().test(Attr::PARAMETER)) {
+ warn |= false;
+ } else if (base->Rank() != 1) {
+ warn |= true;
+ } else if (!base->attrs().test(Attr::ALLOCATABLE) &&
+ !base->attrs().test(Attr::POINTER) &&
+ !base->attrs().test(Attr::VOLATILE)) {
+ // by some reason, dims is not constructed here. For common blocks' variables, it works
+ // it leads to three skipped tests
+ /*
+ if (const ArraySpec *dims{base->GetShape()};
+ dims && dims->IsExplicitShape()) {
+ if (!((*dims)[0].lbound().GetExplicit() == (*dims)[0].ubound().GetExplicit())) {
+ warn |= true;
+ }
+ }
+ */
+ // just give some warnings in code where modules and implicit interfaces are mixed
+ warn |= true;
+ }
+ }
+ if (warn) {
+ context.Warn(common::UsageWarning::PassGlobalVariable, messages.at(),
+ "Passing global variable '%s' from %s '%s' as function argument"_warn_en_US,
+ base->name(), ownerType, ownerName);
+ }
+ }
}
if (IsBOZLiteral(*expr)) {
messages.Say("BOZ argument requires an explicit interface"_err_en_US);
@@ -79,6 +134,36 @@ static void CheckImplicitInterfaceArg(evaluate::ActualArgument &arg,
messages.Say(
"VOLATILE argument requires an explicit interface"_err_en_US);
}
+ // passing global variables
+ // here, scalars and arrays without subscripts are processing
+ bool warn{false};
+ std::string ownerName{""};
+ std::string ownerType{""};
+ if (symbol.flags().test(Symbol::Flag::InCommonBlock)) {
+ const Symbol *common{FindCommonBlockContaining(symbol)};
+ ownerType = "COMMON";
+ ownerName = common->name().ToString();
+ warn |= true;
+ } else if (const auto& owner{symbol.GetUltimate().owner()};
+ owner.IsModule() || owner.IsSubmodule()) {
+ const Scope *module{FindModuleContaining(owner)};
+ ownerType = "MODULE";
+ ownerName = module->GetName()->ToString();
+ if (symbol.attrs().test(Attr::PARAMETER)) {
+ warn |= false;
+ } else if (symbol.Rank() != 1) {
+ warn |= true;
+ } else if (!symbol.attrs().test(Attr::ALLOCATABLE) &&
+ !symbol.attrs().test(Attr::POINTER) &&
+ !symbol.attrs().test(Attr::VOLATILE)) {
+ warn |= true;
+ }
+ }
+ if (warn) {
+ context.Warn(common::UsageWarning::PassGlobalVariable, messages.at(),
+ "Passing global variable '%s' from %s '%s' as function argument"_warn_en_US,
+ symbol.name(), ownerType, ownerName);
+ }
} else if (auto argChars{characteristics::DummyArgument::FromActual(
"actual argument", *expr, context.foldingContext(),
/*forImplicitInterface=*/true)}) {
>From d056747ca323520f6e94981c2a9e6e6258cf7e48 Mon Sep 17 00:00:00 2001
From: "Igor S. Gerasimov" <foxtranigor at gmail.com>
Date: Tue, 23 Sep 2025 16:52:55 +0200
Subject: [PATCH 5/5] Because of something unclear, give a bit more warnings
---
flang/test/Semantics/pass-global-variables.f90 | 3 +++
1 file changed, 3 insertions(+)
diff --git a/flang/test/Semantics/pass-global-variables.f90 b/flang/test/Semantics/pass-global-variables.f90
index 73d1b8e334180..36d5324a14a65 100644
--- a/flang/test/Semantics/pass-global-variables.f90
+++ b/flang/test/Semantics/pass-global-variables.f90
@@ -97,7 +97,9 @@ subroutine module_test(n)
!WARNING: Passing global variable 'i1' from MODULE 'explicit_test_mod' as function argument [-Wpass-global-variable]
call imp_pass_int(i1) !< warn: i1 from common
+ !WARNING: Passing global variable 'i2' from MODULE 'explicit_test_mod' as function argument [-Wpass-global-variable]
call imp_pass_int(i2(1)) !< ok: single element/begin of mem block
+ !WARNING: Passing global variable 'i2' from MODULE 'explicit_test_mod' as function argument [-Wpass-global-variable]
call imp_pass_int(i2(n)) !< ok: single element/begin of mem block
!WARNING: Passing global variable 'i3' from MODULE 'explicit_test_mod' as function argument [-Wpass-global-variable]
call imp_pass_int(i3(1)) !< warn: shape /= [1]
@@ -108,6 +110,7 @@ subroutine module_test(n)
!WARNING: Passing global variable 'i2' from MODULE 'explicit_test_mod' as function argument [-Wpass-global-variable]
call imp_pass_int_1d(i2) !< warn: i2 from module
+ !WARNING: Passing global variable 'i2' from MODULE 'explicit_test_mod' as function argument [-Wpass-global-variable]
call imp_pass_int_1d(i2(n:n+3)) !< ok: mem block
!WARNING: Passing global variable 'i3' from MODULE 'explicit_test_mod' as function argument [-Wpass-global-variable]
call imp_pass_int_1d(i3) !< warn: i3 from module & shape /= [1]
More information about the flang-commits
mailing list