Skip to content

Commit 6d0784c

Browse files
committed
Initial implementation of CheckPassGlobalVariable
1 parent 6dbb895 commit 6d0784c

File tree

1 file changed

+81
-2
lines changed

1 file changed

+81
-2
lines changed

flang/lib/Semantics/check-call.cpp

Lines changed: 81 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,81 @@ namespace characteristics = Fortran::evaluate::characteristics;
2626

2727
namespace Fortran::semantics {
2828

29+
// Raise warnings for some dangerous context of passing global variables
30+
// - any variable from common blocks except
31+
// - 1-element arrays being single member of COMMON
32+
// - avy variable from module except
33+
// - having attribute PARAMETER
34+
// - being arrays having 1-D rank and is not having ALLOCATABLE or POINTER or
35+
// VOLATILE attributes
36+
static void CheckPassGlobalVariable(
37+
const evaluate::Expr<evaluate::SomeType> &actual,
38+
const parser::ContextualMessages &messages, SemanticsContext &context,
39+
evaluate::FoldingContext &foldingContext) {
40+
const Symbol *actualFirstSymbol{evaluate::GetFirstSymbol(actual)};
41+
if (actualFirstSymbol) {
42+
bool warn{false};
43+
std::string ownerType{""};
44+
std::string ownerName{""};
45+
if (actualFirstSymbol->flags().test(Symbol::Flag::InCommonBlock)) {
46+
const Symbol *common{FindCommonBlockContaining(*actualFirstSymbol)};
47+
ownerType = "COMMON";
48+
ownerName = common->name().ToString();
49+
if (!(actualFirstSymbol->Rank() == 1 &&
50+
actualFirstSymbol->offset() == 0)) {
51+
warn |= true;
52+
} else if (actualFirstSymbol->Rank() == 1) {
53+
bool actualIsArrayElement{IsArrayElement(actual) != nullptr};
54+
if (!actualIsArrayElement) {
55+
warn |= true;
56+
}
57+
if (const ArraySpec *dims{actualFirstSymbol->GetShape()};
58+
dims && dims->IsExplicitShape()) {
59+
if (!((*dims)[0].lbound().GetExplicit() ==
60+
(*dims)[0].ubound().GetExplicit())) {
61+
warn |= true;
62+
}
63+
}
64+
if (common->get<CommonBlockDetails>().objects().size() > 1) {
65+
warn |= true;
66+
}
67+
}
68+
} else if (const auto &owner{actualFirstSymbol->GetUltimate().owner()};
69+
owner.IsModule() || owner.IsSubmodule()) {
70+
const Scope *module{FindModuleContaining(owner)};
71+
ownerType = "MODULE";
72+
ownerName = module->GetName()->ToString();
73+
if (actualFirstSymbol->attrs().test(Attr::PARAMETER)) {
74+
warn |= false;
75+
} else if (actualFirstSymbol->Rank() != 1) {
76+
warn |= true;
77+
} else if (!actualFirstSymbol->attrs().test(Attr::ALLOCATABLE) &&
78+
!actualFirstSymbol->attrs().test(Attr::POINTER) &&
79+
!actualFirstSymbol->attrs().test(Attr::VOLATILE)) {
80+
bool actualIsArrayElement{IsArrayElement(actual) != nullptr};
81+
if (!actualIsArrayElement) {
82+
warn |= true;
83+
}
84+
if (const ArraySpec *dims{actualFirstSymbol->GetShape()};
85+
dims && dims->IsExplicitShape()) {
86+
if (!((*dims)[0].lbound().GetExplicit() ==
87+
(*dims)[0].ubound().GetExplicit())) {
88+
warn |= true;
89+
}
90+
}
91+
}
92+
}
93+
if (warn) {
94+
context.Warn(common::UsageWarning::PassGlobalVariable, messages.at(),
95+
"Passing global variable '%s' from %s '%s' as function argument"_warn_en_US,
96+
actualFirstSymbol->name(), ownerType, ownerName);
97+
}
98+
}
99+
}
100+
29101
static void CheckImplicitInterfaceArg(evaluate::ActualArgument &arg,
30-
parser::ContextualMessages &messages, SemanticsContext &context) {
102+
parser::ContextualMessages &messages, SemanticsContext &context,
103+
evaluate::FoldingContext &foldingContext) {
31104
auto restorer{
32105
messages.SetLocation(arg.sourceLocation().value_or(messages.at()))};
33106
if (auto kw{arg.keyword()}) {
@@ -118,6 +191,10 @@ static void CheckImplicitInterfaceArg(evaluate::ActualArgument &arg,
118191
}
119192
}
120193
}
194+
195+
if (const auto *expr{arg.UnwrapExpr()}) {
196+
CheckPassGlobalVariable(*expr, messages, context, foldingContext);
197+
}
121198
}
122199

123200
// F'2023 15.5.2.12p1: "Sequence association only applies when the dummy
@@ -1153,6 +1230,8 @@ static void CheckExplicitDataArg(const characteristics::DummyDataObject &dummy,
11531230
messages.Say(
11541231
"%VAL argument must be a scalar numeric or logical expression"_err_en_US);
11551232
}
1233+
1234+
CheckPassGlobalVariable(actual, messages, context, foldingContext);
11561235
}
11571236

11581237
static void CheckProcedureArg(evaluate::ActualArgument &arg,
@@ -2409,7 +2488,7 @@ bool CheckArguments(const characteristics::Procedure &proc,
24092488
auto restorer{messages.SetMessages(implicitBuffer)};
24102489
for (auto &actual : actuals) {
24112490
if (actual) {
2412-
CheckImplicitInterfaceArg(*actual, messages, context);
2491+
CheckImplicitInterfaceArg(*actual, messages, context, foldingContext);
24132492
}
24142493
}
24152494
}

0 commit comments

Comments
 (0)