Skip to content

Commit 947180e

Browse files
committed
Implementation of -Wpass-global-variable for implicit interfaces
1 parent d53f48b commit 947180e

File tree

1 file changed

+88
-3
lines changed

1 file changed

+88
-3
lines changed

flang/lib/Semantics/check-call.cpp

Lines changed: 88 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,64 @@ static void CheckImplicitInterfaceArg(evaluate::ActualArgument &arg,
5656
"%VAL argument must be a scalar numeric or logical expression"_err_en_US);
5757
}
5858
if (const auto *expr{arg.UnwrapExpr()}) {
59-
if (const Symbol * base{GetFirstSymbol(*expr)};
60-
base && IsFunctionResult(*base)) {
61-
context.NoteDefinedSymbol(*base);
59+
if (const Symbol * base{GetFirstSymbol(*expr)}) {
60+
if (IsFunctionResult(*base)) {
61+
context.NoteDefinedSymbol(*base);
62+
} else {
63+
// passing global variables
64+
// here, arrays with subscripts are processing
65+
bool warn{false};
66+
std::string ownerName{""};
67+
std::string ownerType{""};
68+
if (base->flags().test(Symbol::Flag::InCommonBlock)) {
69+
const Symbol *common{FindCommonBlockContaining(*base)};
70+
ownerType = "COMMON";
71+
ownerName = common->name().ToString();
72+
if (!(base->Rank() == 1 && base->offset() == 0)) {
73+
warn |= true;
74+
} else if (base->Rank() == 1) {
75+
if (const ArraySpec *dims{base->GetShape()};
76+
dims && dims->IsExplicitShape()) {
77+
if (!((*dims)[0].lbound().GetExplicit() == (*dims)[0].ubound().GetExplicit())) {
78+
warn |= true;
79+
}
80+
}
81+
if (common->get<CommonBlockDetails>().objects().size() > 1) {
82+
warn |= true;
83+
}
84+
}
85+
} else if (const auto &owner{base->GetUltimate().owner()};
86+
owner.IsModule() || owner.IsSubmodule()) {
87+
const Scope *module{FindModuleContaining(owner)};
88+
ownerType = "MODULE";
89+
ownerName = module->GetName()->ToString();
90+
if (base->attrs().test(Attr::PARAMETER)) {
91+
warn |= false;
92+
} else if (base->Rank() != 1) {
93+
warn |= true;
94+
} else if (!base->attrs().test(Attr::ALLOCATABLE) &&
95+
!base->attrs().test(Attr::POINTER) &&
96+
!base->attrs().test(Attr::VOLATILE)) {
97+
// by some reason, dims is not constructed here. For common blocks' variables, it works
98+
// it leads to three skipped tests
99+
/*
100+
if (const ArraySpec *dims{base->GetShape()};
101+
dims && dims->IsExplicitShape()) {
102+
if (!((*dims)[0].lbound().GetExplicit() == (*dims)[0].ubound().GetExplicit())) {
103+
warn |= true;
104+
}
105+
}
106+
*/
107+
// just give some warnings in code where modules and implicit interfaces are mixed
108+
warn |= true;
109+
}
110+
}
111+
if (warn) {
112+
context.Warn(common::UsageWarning::PassGlobalVariable, messages.at(),
113+
"Passing global variable '%s' from %s '%s' as function argument"_warn_en_US,
114+
base->name(), ownerType, ownerName);
115+
}
116+
}
62117
}
63118
if (IsBOZLiteral(*expr)) {
64119
messages.Say("BOZ argument requires an explicit interface"_err_en_US);
@@ -79,6 +134,36 @@ static void CheckImplicitInterfaceArg(evaluate::ActualArgument &arg,
79134
messages.Say(
80135
"VOLATILE argument requires an explicit interface"_err_en_US);
81136
}
137+
// passing global variables
138+
// here, scalars and arrays without subscripts are processing
139+
bool warn{false};
140+
std::string ownerName{""};
141+
std::string ownerType{""};
142+
if (symbol.flags().test(Symbol::Flag::InCommonBlock)) {
143+
const Symbol *common{FindCommonBlockContaining(symbol)};
144+
ownerType = "COMMON";
145+
ownerName = common->name().ToString();
146+
warn |= true;
147+
} else if (const auto& owner{symbol.GetUltimate().owner()};
148+
owner.IsModule() || owner.IsSubmodule()) {
149+
const Scope *module{FindModuleContaining(owner)};
150+
ownerType = "MODULE";
151+
ownerName = module->GetName()->ToString();
152+
if (symbol.attrs().test(Attr::PARAMETER)) {
153+
warn |= false;
154+
} else if (symbol.Rank() != 1) {
155+
warn |= true;
156+
} else if (!symbol.attrs().test(Attr::ALLOCATABLE) &&
157+
!symbol.attrs().test(Attr::POINTER) &&
158+
!symbol.attrs().test(Attr::VOLATILE)) {
159+
warn |= true;
160+
}
161+
}
162+
if (warn) {
163+
context.Warn(common::UsageWarning::PassGlobalVariable, messages.at(),
164+
"Passing global variable '%s' from %s '%s' as function argument"_warn_en_US,
165+
symbol.name(), ownerType, ownerName);
166+
}
82167
} else if (auto argChars{characteristics::DummyArgument::FromActual(
83168
"actual argument", *expr, context.foldingContext(),
84169
/*forImplicitInterface=*/true)}) {

0 commit comments

Comments
 (0)