Skip to content

Commit 861dd9b

Browse files
committed
[flang] Catch bad members of BIND(C) COMMON block
Variables that can't be BIND(C), like pointers, can't be in a BIND(C) common block, either. Fixes #148922.
1 parent 309bb1e commit 861dd9b

File tree

2 files changed

+36
-10
lines changed

2 files changed

+36
-10
lines changed

flang/lib/Semantics/check-declarations.cpp

Lines changed: 29 additions & 10 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,28 @@ 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+
if (auto *msg{messages_.Say(symbol.name(),
532+
"'%s' may not be a member of BIND(C) COMMON block /%s/"_err_en_US,
533+
ref->name(), symbol.name())}) {
534+
for (parser::Message &reason : msgs.messages()) {
535+
reason.set_severity(parser::Severity::Because);
536+
msg->Attach(std::move(reason));
537+
}
538+
}
539+
}
540+
}
541+
}
525542
}
526-
for (MutableSymbolRef ref : symbol.get<CommonBlockDetails>().objects()) {
543+
for (auto ref : symbol.get<CommonBlockDetails>().objects()) {
527544
if (ref->test(Symbol::Flag::CrayPointee)) {
528545
messages_.Say(ref->name(),
529546
"Cray pointee '%s' may not be a member of a COMMON block"_err_en_US,
@@ -3154,14 +3171,16 @@ parser::Messages CheckHelper::WhyNotInteroperableDerivedType(
31543171
}
31553172

31563173
parser::Messages CheckHelper::WhyNotInteroperableObject(
3157-
const Symbol &symbol, bool allowNonInteroperableType) {
3174+
const Symbol &symbol, bool allowNonInteroperableType, bool forCommonBlock) {
31583175
parser::Messages msgs;
3159-
if (examinedByWhyNotInteroperable_.find(symbol) !=
3160-
examinedByWhyNotInteroperable_.end()) {
3161-
return msgs;
3176+
if (!forCommonBlock) {
3177+
if (examinedByWhyNotInteroperable_.find(symbol) !=
3178+
examinedByWhyNotInteroperable_.end()) {
3179+
return msgs;
3180+
}
3181+
examinedByWhyNotInteroperable_.insert(symbol);
31623182
}
31633183
bool isExplicitBindC{symbol.attrs().test(Attr::BIND_C)};
3164-
examinedByWhyNotInteroperable_.insert(symbol);
31653184
CHECK(symbol.has<ObjectEntityDetails>());
31663185
if (isExplicitBindC && !symbol.owner().IsModule()) {
31673186
msgs.Say(symbol.name(),
@@ -3338,8 +3357,8 @@ parser::Messages CheckHelper::WhyNotInteroperableProcedure(
33383357
// on the C side by either a cdesc_t * or a void *. F'2023 18.3.7 (5)
33393358
bool allowNonInteroperableType{!dummy->attrs().test(Attr::VALUE) &&
33403359
(IsDescriptor(*dummy) || IsAssumedType(*dummy))};
3341-
dummyMsgs =
3342-
WhyNotInteroperableObject(*dummy, allowNonInteroperableType);
3360+
dummyMsgs = WhyNotInteroperableObject(
3361+
*dummy, allowNonInteroperableType, /*forCommonBlock=*/false);
33433362
} else {
33443363
CheckBindC(*dummy);
33453364
}

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+
!BECAUSE: A scalar interoperable variable may not be ALLOCATABLE or POINTER
5+
common /blk/ x
6+
integer, pointer :: x
7+
end

0 commit comments

Comments
 (0)