forked from OSchip/llvm-project
[flang] Enforce C1552, no binding labels allowed for internal procedures
If BIND(C) appears on an internal procedure, it must have a null binding label, i.e. BIND(C,NAME=""). Also address conflicts with D127725 which was merged during development. Differential Revision: https://reviews.llvm.org/D128676
This commit is contained in:
parent
eab2a06f0f
commit
cfd474e0d0
|
@ -1869,10 +1869,8 @@ void CheckHelper::CheckGenericOps(const Scope &scope) {
|
||||||
|
|
||||||
static const std::string *DefinesBindCName(const Symbol &symbol) {
|
static const std::string *DefinesBindCName(const Symbol &symbol) {
|
||||||
const auto *subp{symbol.detailsIf<SubprogramDetails>()};
|
const auto *subp{symbol.detailsIf<SubprogramDetails>()};
|
||||||
if ((subp && !subp->isInterface() &&
|
if ((subp && !subp->isInterface()) || symbol.has<ObjectEntityDetails>() ||
|
||||||
ClassifyProcedure(symbol) != ProcedureDefinitionClass::Internal) ||
|
symbol.has<CommonBlockDetails>()) {
|
||||||
symbol.has<ObjectEntityDetails>() || symbol.has<CommonBlockDetails>() ||
|
|
||||||
symbol.has<ProcEntityDetails>()) {
|
|
||||||
// Symbol defines data or entry point
|
// Symbol defines data or entry point
|
||||||
return symbol.GetBindName();
|
return symbol.GetBindName();
|
||||||
} else {
|
} else {
|
||||||
|
@ -1893,14 +1891,15 @@ void CheckHelper::CheckBindC(const Symbol &symbol) {
|
||||||
auto pair{bindC_.emplace(*name, symbol)};
|
auto pair{bindC_.emplace(*name, symbol)};
|
||||||
if (!pair.second) {
|
if (!pair.second) {
|
||||||
const Symbol &other{*pair.first->second};
|
const Symbol &other{*pair.first->second};
|
||||||
// Two common blocks with the same name can have the same BIND(C) name.
|
if (symbol.has<CommonBlockDetails>() && other.has<CommonBlockDetails>() &&
|
||||||
if ((!symbol.has<CommonBlockDetails>() ||
|
symbol.name() == other.name()) {
|
||||||
symbol.name() != other.name()) &&
|
// Two common blocks can have the same BIND(C) name so long as
|
||||||
DefinesBindCName(other) && !context_.HasError(other)) {
|
// they're not in the same scope.
|
||||||
|
} else if (!context_.HasError(other)) {
|
||||||
if (auto *msg{messages_.Say(symbol.name(),
|
if (auto *msg{messages_.Say(symbol.name(),
|
||||||
"Two symbols have the same BIND(C) name '%s'"_err_en_US,
|
"Two entities have the same BIND(C) name '%s'"_err_en_US,
|
||||||
*name)}) {
|
*name)}) {
|
||||||
msg->Attach(other.name(), "Conflicting symbol"_en_US);
|
msg->Attach(other.name(), "Conflicting declaration"_en_US);
|
||||||
}
|
}
|
||||||
context_.SetError(symbol);
|
context_.SetError(symbol);
|
||||||
context_.SetError(other);
|
context_.SetError(other);
|
||||||
|
|
|
@ -1662,12 +1662,18 @@ void AttrsVisitor::SetBindNameOn(Symbol &symbol) {
|
||||||
}
|
}
|
||||||
std::optional<std::string> label{
|
std::optional<std::string> label{
|
||||||
evaluate::GetScalarConstantValue<evaluate::Ascii>(bindName_)};
|
evaluate::GetScalarConstantValue<evaluate::Ascii>(bindName_)};
|
||||||
// 18.9.2(2): discard leading and trailing blanks, ignore if all blank
|
if (ClassifyProcedure(symbol) == ProcedureDefinitionClass::Internal) {
|
||||||
|
if (label) { // C1552: no NAME= allowed even if null
|
||||||
|
Say(symbol.name(),
|
||||||
|
"An internal procedure may not have a BIND(C,NAME=) binding label"_err_en_US);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 18.9.2(2): discard leading and trailing blanks
|
||||||
if (label) {
|
if (label) {
|
||||||
auto first{label->find_first_not_of(" ")};
|
auto first{label->find_first_not_of(" ")};
|
||||||
if (first == std::string::npos) {
|
if (first == std::string::npos) {
|
||||||
// Empty NAME= means no binding at all (18.10.2p2)
|
// Empty NAME= means no binding at all (18.10.2p2)
|
||||||
Say(currStmtSource().value(), "Blank binding label ignored"_warn_en_US);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto last{label->find_last_not_of(" ")};
|
auto last{label->find_last_not_of(" ")};
|
||||||
|
@ -4172,10 +4178,10 @@ Symbol &DeclarationVisitor::DeclareUnknownEntity(
|
||||||
SetType(name, *type);
|
SetType(name, *type);
|
||||||
}
|
}
|
||||||
charInfo_.length.reset();
|
charInfo_.length.reset();
|
||||||
SetBindNameOn(symbol);
|
|
||||||
if (symbol.attrs().test(Attr::EXTERNAL)) {
|
if (symbol.attrs().test(Attr::EXTERNAL)) {
|
||||||
ConvertToProcEntity(symbol);
|
ConvertToProcEntity(symbol);
|
||||||
}
|
}
|
||||||
|
SetBindNameOn(symbol);
|
||||||
return symbol;
|
return symbol;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1091,7 +1091,9 @@ const Symbol *FindSeparateModuleSubprogramInterface(const Symbol *proc) {
|
||||||
|
|
||||||
ProcedureDefinitionClass ClassifyProcedure(const Symbol &symbol) { // 15.2.2
|
ProcedureDefinitionClass ClassifyProcedure(const Symbol &symbol) { // 15.2.2
|
||||||
const Symbol &ultimate{symbol.GetUltimate()};
|
const Symbol &ultimate{symbol.GetUltimate()};
|
||||||
if (ultimate.attrs().test(Attr::INTRINSIC)) {
|
if (!IsProcedure(ultimate)) {
|
||||||
|
return ProcedureDefinitionClass::None;
|
||||||
|
} else if (ultimate.attrs().test(Attr::INTRINSIC)) {
|
||||||
return ProcedureDefinitionClass::Intrinsic;
|
return ProcedureDefinitionClass::Intrinsic;
|
||||||
} else if (ultimate.attrs().test(Attr::EXTERNAL)) {
|
} else if (ultimate.attrs().test(Attr::EXTERNAL)) {
|
||||||
return ProcedureDefinitionClass::External;
|
return ProcedureDefinitionClass::External;
|
||||||
|
|
|
@ -3,14 +3,14 @@
|
||||||
|
|
||||||
module m1
|
module m1
|
||||||
integer, bind(c, name="x1") :: x1
|
integer, bind(c, name="x1") :: x1
|
||||||
!ERROR: Two symbols have the same BIND(C) name 'x1'
|
!ERROR: Two entities have the same BIND(C) name 'x1'
|
||||||
integer, bind(c, name=" x1 ") :: x2
|
integer, bind(c, name=" x1 ") :: x2
|
||||||
contains
|
contains
|
||||||
subroutine x3() bind(c, name="x3")
|
subroutine x3() bind(c, name="x3")
|
||||||
end subroutine
|
end subroutine
|
||||||
end module
|
end module
|
||||||
|
|
||||||
!ERROR: Two symbols have the same BIND(C) name 'x3'
|
!ERROR: Two entities have the same BIND(C) name 'x3'
|
||||||
subroutine x4() bind(c, name=" x3 ")
|
subroutine x4() bind(c, name=" x3 ")
|
||||||
end subroutine
|
end subroutine
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@ subroutine sub(x, y)
|
||||||
end
|
end
|
||||||
end interface
|
end interface
|
||||||
|
|
||||||
!ERROR: Two symbols have the same BIND(C) name 'aaa'
|
!Acceptable (as an extension)
|
||||||
procedure(proc), bind(c, name="aaa") :: pc1, pc2
|
procedure(proc), bind(c, name="aaa") :: pc1, pc2
|
||||||
|
|
||||||
!ERROR: BIND(C) procedure with NAME= specified can neither have POINTER attribute nor be a dummy procedure
|
!ERROR: BIND(C) procedure with NAME= specified can neither have POINTER attribute nor be a dummy procedure
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
! RUN: %python %S/test_errors.py %s %flang_fc1
|
||||||
|
! Check for C1552
|
||||||
|
program main
|
||||||
|
contains
|
||||||
|
subroutine internal1() bind(c) ! ok
|
||||||
|
end subroutine
|
||||||
|
!ERROR: An internal procedure may not have a BIND(C,NAME=) binding label
|
||||||
|
subroutine internal2() bind(c,name="internal2")
|
||||||
|
end subroutine
|
||||||
|
!ERROR: An internal procedure may not have a BIND(C,NAME=) binding label
|
||||||
|
subroutine internal3() bind(c,name="")
|
||||||
|
end subroutine
|
||||||
|
end
|
|
@ -5,17 +5,17 @@ module m
|
||||||
|
|
||||||
integer :: x, y, z, w, i, j, k
|
integer :: x, y, z, w, i, j, k
|
||||||
|
|
||||||
!ERROR: Two symbols have the same BIND(C) name 'aa'
|
!ERROR: Two entities have the same BIND(C) name 'aa'
|
||||||
common /blk1/ x, /blk2/ y
|
common /blk1/ x, /blk2/ y
|
||||||
bind(c, name="aa") :: /blk1/, /blk2/
|
bind(c, name="aa") :: /blk1/, /blk2/
|
||||||
|
|
||||||
integer :: t
|
integer :: t
|
||||||
!ERROR: Two symbols have the same BIND(C) name 'bb'
|
!ERROR: Two entities have the same BIND(C) name 'bb'
|
||||||
common /blk3/ z
|
common /blk3/ z
|
||||||
bind(c, name="bb") :: /blk3/, t
|
bind(c, name="bb") :: /blk3/, t
|
||||||
|
|
||||||
integer :: t2
|
integer :: t2
|
||||||
!ERROR: Two symbols have the same BIND(C) name 'cc'
|
!ERROR: Two entities have the same BIND(C) name 'cc'
|
||||||
common /blk4/ w
|
common /blk4/ w
|
||||||
bind(c, name="cc") :: t2, /blk4/
|
bind(c, name="cc") :: t2, /blk4/
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ module m
|
||||||
bind(c, name="dd") :: /blk5/
|
bind(c, name="dd") :: /blk5/
|
||||||
bind(c, name="ee") :: /blk5/
|
bind(c, name="ee") :: /blk5/
|
||||||
|
|
||||||
!ERROR: Two symbols have the same BIND(C) name 'ff'
|
!ERROR: Two entities have the same BIND(C) name 'ff'
|
||||||
common /blk6/ j, /blk7/ k
|
common /blk6/ j, /blk7/ k
|
||||||
bind(c, name="ff") :: /blk6/
|
bind(c, name="ff") :: /blk6/
|
||||||
bind(c, name="ff") :: /blk7/
|
bind(c, name="ff") :: /blk7/
|
||||||
|
@ -34,7 +34,7 @@ module m
|
||||||
bind(c, name="gg") :: s1
|
bind(c, name="gg") :: s1
|
||||||
bind(c, name="hh") :: s1
|
bind(c, name="hh") :: s1
|
||||||
|
|
||||||
!ERROR: Two symbols have the same BIND(C) name 'ii'
|
!ERROR: Two entities have the same BIND(C) name 'ii'
|
||||||
integer :: s2, s3
|
integer :: s2, s3
|
||||||
bind(c, name="ii") :: s2
|
bind(c, name="ii") :: s2
|
||||||
bind(c, name="ii") :: s3
|
bind(c, name="ii") :: s3
|
||||||
|
@ -66,6 +66,6 @@ module a
|
||||||
end module
|
end module
|
||||||
|
|
||||||
module b
|
module b
|
||||||
!ERROR: Two symbols have the same BIND(C) name 'int'
|
!ERROR: Two entities have the same BIND(C) name 'int'
|
||||||
integer, bind(c, name="int") :: i
|
integer, bind(c, name="int") :: i
|
||||||
end module
|
end module
|
||||||
|
|
Loading…
Reference in New Issue