Skip to content

Commit 3de11b7

Browse files
authored
[flang] Catch bad members of BIND(C) COMMON block (#148971)
Variables that can't be BIND(C), like pointers, can't be in a BIND(C) common block, either. Fixes #148922.
1 parent bbcdad1 commit 3de11b7

File tree

2 files changed

+44
-11
lines changed

2 files changed

+44
-11
lines changed

flang/lib/Semantics/check-declarations.cpp

Lines changed: 37 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -151,8 +151,8 @@ class CheckHelper {
151151
void CheckProcedureAssemblyName(const Symbol &symbol);
152152
void CheckExplicitSave(const Symbol &);
153153
parser::Messages WhyNotInteroperableDerivedType(const Symbol &);
154-
parser::Messages WhyNotInteroperableObject(
155-
const Symbol &, bool allowNonInteroperableType = false);
154+
parser::Messages WhyNotInteroperableObject(const Symbol &,
155+
bool allowNonInteroperableType = false, bool forCommonBlock = false);
156156
parser::Messages WhyNotInteroperableFunctionResult(const Symbol &);
157157
parser::Messages WhyNotInteroperableProcedure(const Symbol &, bool isError);
158158
void CheckBindC(const Symbol &);
@@ -519,11 +519,35 @@ void CheckHelper::Check(const Symbol &symbol) {
519519
}
520520

521521
void CheckHelper::CheckCommonBlock(const Symbol &symbol) {
522+
auto restorer{messages_.SetLocation(symbol.name())};
522523
CheckGlobalName(symbol);
523524
if (symbol.attrs().test(Attr::BIND_C)) {
524525
CheckBindC(symbol);
526+
for (auto ref : symbol.get<CommonBlockDetails>().objects()) {
527+
if (ref->has<ObjectEntityDetails>()) {
528+
if (auto msgs{WhyNotInteroperableObject(*ref,
529+
/*allowInteroperableType=*/false, /*forCommonBlock=*/true)};
530+
!msgs.empty()) {
531+
parser::Message &reason{msgs.messages().front()};
532+
parser::Message *msg{nullptr};
533+
if (reason.IsFatal()) {
534+
msg = messages_.Say(symbol.name(),
535+
"'%s' may not be a member of BIND(C) COMMON block /%s/"_err_en_US,
536+
ref->name(), symbol.name());
537+
} else {
538+
msg = messages_.Say(symbol.name(),
539+
"'%s' should not be a member of BIND(C) COMMON block /%s/"_warn_en_US,
540+
ref->name(), symbol.name());
541+
}
542+
if (msg) {
543+
msg->Attach(
544+
std::move(reason.set_severity(parser::Severity::Because)));
545+
}
546+
}
547+
}
548+
}
525549
}
526-
for (MutableSymbolRef ref : symbol.get<CommonBlockDetails>().objects()) {
550+
for (auto ref : symbol.get<CommonBlockDetails>().objects()) {
527551
if (ref->test(Symbol::Flag::CrayPointee)) {
528552
messages_.Say(ref->name(),
529553
"Cray pointee '%s' may not be a member of a COMMON block"_err_en_US,
@@ -3154,14 +3178,16 @@ parser::Messages CheckHelper::WhyNotInteroperableDerivedType(
31543178
}
31553179

31563180
parser::Messages CheckHelper::WhyNotInteroperableObject(
3157-
const Symbol &symbol, bool allowNonInteroperableType) {
3181+
const Symbol &symbol, bool allowNonInteroperableType, bool forCommonBlock) {
31583182
parser::Messages msgs;
3159-
if (examinedByWhyNotInteroperable_.find(symbol) !=
3160-
examinedByWhyNotInteroperable_.end()) {
3161-
return msgs;
3183+
if (!forCommonBlock) {
3184+
if (examinedByWhyNotInteroperable_.find(symbol) !=
3185+
examinedByWhyNotInteroperable_.end()) {
3186+
return msgs;
3187+
}
3188+
examinedByWhyNotInteroperable_.insert(symbol);
31623189
}
31633190
bool isExplicitBindC{symbol.attrs().test(Attr::BIND_C)};
3164-
examinedByWhyNotInteroperable_.insert(symbol);
31653191
CHECK(symbol.has<ObjectEntityDetails>());
31663192
if (isExplicitBindC && !symbol.owner().IsModule()) {
31673193
msgs.Say(symbol.name(),
@@ -3258,7 +3284,7 @@ parser::Messages CheckHelper::WhyNotInteroperableObject(
32583284
msgs.Say(symbol.name(),
32593285
"An interoperable pointer must not be CONTIGUOUS"_err_en_US);
32603286
}
3261-
if (msgs.AnyFatalError()) {
3287+
if (!forCommonBlock && msgs.AnyFatalError()) {
32623288
examinedByWhyNotInteroperable_.erase(symbol);
32633289
}
32643290
return msgs;
@@ -3338,8 +3364,8 @@ parser::Messages CheckHelper::WhyNotInteroperableProcedure(
33383364
// on the C side by either a cdesc_t * or a void *. F'2023 18.3.7 (5)
33393365
bool allowNonInteroperableType{!dummy->attrs().test(Attr::VALUE) &&
33403366
(IsDescriptor(*dummy) || IsAssumedType(*dummy))};
3341-
dummyMsgs =
3342-
WhyNotInteroperableObject(*dummy, allowNonInteroperableType);
3367+
dummyMsgs = WhyNotInteroperableObject(
3368+
*dummy, allowNonInteroperableType, /*forCommonBlock=*/false);
33433369
} else {
33443370
CheckBindC(*dummy);
33453371
}

flang/test/Semantics/bind-c18.f90

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
! RUN: %python %S/test_errors.py %s %flang_fc1
2+
bind(c) :: /blk/
3+
!ERROR: 'x' may not be a member of BIND(C) COMMON block /blk/
4+
common /blk/ x
5+
!BECAUSE: A scalar interoperable variable may not be ALLOCATABLE or POINTER
6+
integer, pointer :: x
7+
end

0 commit comments

Comments
 (0)