Skip to content

Commit 982614f

Browse files
committed
[flang] Warn about inconsistent external procedure interfaces
When multiple scopes in a compilation define interfaces (explicit or implicit) for an external procedure, warn when those interfaces are inconsistent. Differential Revision: https://reviews.llvm.org/D146574
1 parent fe8abcc commit 982614f

File tree

6 files changed

+78
-55
lines changed

6 files changed

+78
-55
lines changed

flang/lib/Semantics/check-declarations.cpp

Lines changed: 30 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ class CheckHelper {
6666
void CheckArraySpec(const Symbol &, const ArraySpec &);
6767
void CheckProcEntity(const Symbol &, const ProcEntityDetails &);
6868
void CheckSubprogram(const Symbol &, const SubprogramDetails &);
69-
void CheckLocalVsGlobal(const Symbol &);
69+
void CheckExternal(const Symbol &);
7070
void CheckAssumedTypeEntity(const Symbol &, const ObjectEntityDetails &);
7171
void CheckDerivedType(const Symbol &, const DerivedTypeDetails &);
7272
bool CheckFinal(
@@ -161,6 +161,8 @@ class CheckHelper {
161161
std::map<std::pair<SourceName, const Symbol *>, SymbolRef> moduleProcs_;
162162
// Collection of symbols with global names, BIND(C) or otherwise
163163
std::map<std::string, SymbolRef> globalNames_;
164+
// Collection of external procedures without global definitions
165+
std::map<std::string, SymbolRef> externalNames_;
164166
};
165167

166168
class DistinguishabilityHelper {
@@ -957,7 +959,7 @@ void CheckHelper::CheckProcEntity(
957959
"Procedure '%s' with SAVE attribute must also have POINTER attribute"_err_en_US,
958960
symbol.name());
959961
}
960-
CheckLocalVsGlobal(symbol);
962+
CheckExternal(symbol);
961963
}
962964

963965
// When a module subprogram has the MODULE prefix the following must match
@@ -1098,17 +1100,18 @@ void CheckHelper::CheckSubprogram(
10981100
"A function interface may not declare an assumed-length CHARACTER(*) result"_err_en_US);
10991101
}
11001102
}
1101-
CheckLocalVsGlobal(symbol);
1103+
CheckExternal(symbol);
11021104
CheckModuleProcedureDef(symbol);
11031105
}
11041106

1105-
void CheckHelper::CheckLocalVsGlobal(const Symbol &symbol) {
1107+
void CheckHelper::CheckExternal(const Symbol &symbol) {
11061108
if (IsExternal(symbol)) {
1107-
if (const Symbol *global{FindGlobal(symbol)}; global && global != &symbol) {
1108-
std::string interfaceName{symbol.name().ToString()};
1109-
if (const auto *bind{symbol.GetBindName()}) {
1110-
interfaceName = *bind;
1111-
}
1109+
std::string interfaceName{symbol.name().ToString()};
1110+
if (const auto *bind{symbol.GetBindName()}) {
1111+
interfaceName = *bind;
1112+
}
1113+
if (const Symbol * global{FindGlobal(symbol)};
1114+
global && global != &symbol) {
11121115
std::string definitionName{global->name().ToString()};
11131116
if (const auto *bind{global->GetBindName()}) {
11141117
definitionName = *bind;
@@ -1146,6 +1149,24 @@ void CheckHelper::CheckLocalVsGlobal(const Symbol &symbol) {
11461149
evaluate::AttachDeclaration(msg, symbol);
11471150
}
11481151
}
1152+
} else if (auto iter{externalNames_.find(interfaceName)};
1153+
iter != externalNames_.end()) {
1154+
const Symbol &previous{*iter->second};
1155+
if (auto chars{Characterize(symbol)}) {
1156+
if (auto previousChars{Characterize(previous)}) {
1157+
std::string whyNot;
1158+
if (!chars->IsCompatibleWith(*previousChars, &whyNot)) {
1159+
if (auto *msg{messages_.Say(
1160+
"The external interface '%s' is not compatible with an earlier definition (%s)"_warn_en_US,
1161+
symbol.name(), whyNot)}) {
1162+
evaluate::AttachDeclaration(msg, previous);
1163+
evaluate::AttachDeclaration(msg, symbol);
1164+
}
1165+
}
1166+
}
1167+
}
1168+
} else {
1169+
externalNames_.emplace(interfaceName, symbol);
11491170
}
11501171
}
11511172
}

flang/test/Semantics/null-init.f90

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ module m6
3737

3838
module m7
3939
interface
40+
!WARNING: The external interface 'null' is not compatible with an earlier definition (incompatible procedure attributes: ImplicitInterface)
4041
function null() result(p)
4142
integer, pointer :: p
4243
end function

flang/test/Semantics/resolve24.f90

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,11 @@ function f()
1414
subroutine test2
1515
!ERROR: Generic interface 'foo' has both a function and a subroutine
1616
interface foo
17-
function f1(x)
17+
function t2f1(x)
1818
end function
1919
subroutine s()
2020
end subroutine
21-
function f2(x, y)
21+
function t2f2(x, y)
2222
end function
2323
end interface
2424
end subroutine
@@ -48,13 +48,13 @@ subroutine s()
4848

4949
subroutine test5
5050
interface foo
51-
function f1()
51+
function t5f1()
5252
end function
5353
end interface
5454
interface bar
55-
subroutine s1()
55+
subroutine t5s1()
5656
end subroutine
57-
subroutine s2(x)
57+
subroutine t5s2(x)
5858
end subroutine
5959
end interface
6060
!ERROR: Cannot call function 'foo' like a subroutine

flang/test/Semantics/resolve53.f90

Lines changed: 37 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -25,22 +25,22 @@ subroutine s4(x)
2525
end
2626

2727
module m2
28-
!ERROR: Generic 'g' may not have specific procedures 's1' and 's2' as their interfaces are not distinguishable
28+
!ERROR: Generic 'g' may not have specific procedures 'm2s1' and 'm2s2' as their interfaces are not distinguishable
2929
interface g
30-
subroutine s1(x)
30+
subroutine m2s1(x)
3131
end subroutine
32-
subroutine s2(x)
32+
subroutine m2s2(x)
3333
real x
3434
end subroutine
3535
end interface
3636
end
3737

3838
module m3
39-
!ERROR: Generic 'g' may not have specific procedures 'f1' and 'f2' as their interfaces are not distinguishable
39+
!ERROR: Generic 'g' may not have specific procedures 'm3f1' and 'm3f2' as their interfaces are not distinguishable
4040
interface g
41-
integer function f1()
41+
integer function m3f1()
4242
end function
43-
real function f2()
43+
real function m3f2()
4444
end function
4545
end interface
4646
end
@@ -51,11 +51,11 @@ module m4
5151
type, extends(t1) :: t2
5252
end type
5353
interface g
54-
subroutine s1(x)
54+
subroutine m4s1(x)
5555
import :: t1
5656
type(t1) :: x
5757
end
58-
subroutine s2(x)
58+
subroutine m4s2(x)
5959
import :: t2
6060
type(t2) :: x
6161
end
@@ -65,91 +65,91 @@ subroutine s2(x)
6565
! These are all different ranks so they are distinguishable
6666
module m5
6767
interface g
68-
subroutine s1(x)
68+
subroutine m5s1(x)
6969
real x
7070
end subroutine
71-
subroutine s2(x)
71+
subroutine m5s2(x)
7272
real x(:)
7373
end subroutine
74-
subroutine s3(x)
74+
subroutine m5s3(x)
7575
real x(:,:)
7676
end subroutine
7777
end interface
7878
end
7979

8080
module m6
8181
use m5
82-
!ERROR: Generic 'g' may not have specific procedures 's1' and 's4' as their interfaces are not distinguishable
82+
!ERROR: Generic 'g' may not have specific procedures 'm5s1' and 'm6s4' as their interfaces are not distinguishable
8383
interface g
84-
subroutine s4(x)
84+
subroutine m6s4(x)
8585
end subroutine
8686
end interface
8787
end
8888

8989
module m7
9090
use m5
91-
!ERROR: Generic 'g' may not have specific procedures 's1' and 's5' as their interfaces are not distinguishable
92-
!ERROR: Generic 'g' may not have specific procedures 's2' and 's5' as their interfaces are not distinguishable
93-
!ERROR: Generic 'g' may not have specific procedures 's3' and 's5' as their interfaces are not distinguishable
91+
!ERROR: Generic 'g' may not have specific procedures 'm5s1' and 'm7s5' as their interfaces are not distinguishable
92+
!ERROR: Generic 'g' may not have specific procedures 'm5s2' and 'm7s5' as their interfaces are not distinguishable
93+
!ERROR: Generic 'g' may not have specific procedures 'm5s3' and 'm7s5' as their interfaces are not distinguishable
9494
interface g
95-
subroutine s5(x)
95+
subroutine m7s5(x)
9696
real x(..)
9797
end subroutine
9898
end interface
9999
end
100100

101101
! Two procedures that differ only by attributes are not distinguishable
102102
module m8
103-
!ERROR: Generic 'g' may not have specific procedures 's1' and 's2' as their interfaces are not distinguishable
103+
!ERROR: Generic 'g' may not have specific procedures 'm8s1' and 'm8s2' as their interfaces are not distinguishable
104104
interface g
105-
pure subroutine s1(x)
105+
pure subroutine m8s1(x)
106106
real, intent(in) :: x
107107
end subroutine
108-
subroutine s2(x)
108+
subroutine m8s2(x)
109109
real, intent(in) :: x
110110
end subroutine
111111
end interface
112112
end
113113

114114
module m9
115-
!ERROR: Generic 'g' may not have specific procedures 's1' and 's2' as their interfaces are not distinguishable
115+
!ERROR: Generic 'g' may not have specific procedures 'm9s1' and 'm9s2' as their interfaces are not distinguishable
116116
interface g
117-
subroutine s1(x)
117+
subroutine m9s1(x)
118118
real :: x(10)
119119
end subroutine
120-
subroutine s2(x)
120+
subroutine m9s2(x)
121121
real :: x(100)
122122
end subroutine
123123
end interface
124124
end
125125

126126
module m10
127-
!ERROR: Generic 'g' may not have specific procedures 's1' and 's2' as their interfaces are not distinguishable
127+
!ERROR: Generic 'g' may not have specific procedures 'm10s1' and 'm10s2' as their interfaces are not distinguishable
128128
interface g
129-
subroutine s1(x)
129+
subroutine m10s1(x)
130130
real :: x(10)
131131
end subroutine
132-
subroutine s2(x)
132+
subroutine m10s2(x)
133133
real :: x(..)
134134
end subroutine
135135
end interface
136136
end
137137

138138
program m11
139139
interface g1
140-
subroutine s1(x)
140+
subroutine m11s1(x)
141141
real, pointer, intent(out) :: x
142142
end subroutine
143-
subroutine s2(x)
143+
subroutine m11s2(x)
144144
real, allocatable :: x
145145
end subroutine
146146
end interface
147-
!ERROR: Generic 'g2' may not have specific procedures 's3' and 's4' as their interfaces are not distinguishable
147+
!ERROR: Generic 'g2' may not have specific procedures 'm11s3' and 'm11s4' as their interfaces are not distinguishable
148148
interface g2
149-
subroutine s3(x)
149+
subroutine m11s3(x)
150150
real, pointer, intent(in) :: x
151151
end subroutine
152-
subroutine s4(x)
152+
subroutine m11s4(x)
153153
real, allocatable :: x
154154
end subroutine
155155
end interface
@@ -458,24 +458,24 @@ integer function f3(i, j)
458458

459459
module m20
460460
interface operator(.not.)
461-
real function f(x)
461+
real function m20f(x)
462462
character(*),intent(in) :: x
463463
end function
464464
end interface
465465
interface operator(+)
466-
procedure f
466+
procedure m20f
467467
end interface
468468
end module
469469

470470
subroutine subr1()
471471
use m20
472472
interface operator(.not.)
473-
!ERROR: Procedure 'f' from module 'm20' is already specified in generic 'OPERATOR(.NOT.)'
474-
procedure f
473+
!ERROR: Procedure 'm20f' from module 'm20' is already specified in generic 'OPERATOR(.NOT.)'
474+
procedure m20f
475475
end interface
476476
interface operator(+)
477-
!ERROR: Procedure 'f' from module 'm20' is already specified in generic 'OPERATOR(+)'
478-
procedure f
477+
!ERROR: Procedure 'm20f' from module 'm20' is already specified in generic 'OPERATOR(+)'
478+
procedure m20f
479479
end interface
480480
end subroutine subr1
481481

flang/test/Semantics/resolve62.f90

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@
22
! Resolve generic based on number of arguments
33
subroutine subr1
44
interface f
5-
real function f1(x)
5+
real function s1f1(x)
66
optional :: x
77
end
8-
real function f2(x, y)
8+
real function s1f2(x, y)
99
end
1010
end interface
1111
z = f(1.0)
@@ -17,10 +17,10 @@ real function f2(x, y)
1717
! Elemental and non-element function both match: non-elemental one should be used
1818
subroutine subr2
1919
interface f
20-
logical elemental function f1(x)
20+
logical elemental function s2f1(x)
2121
intent(in) :: x
2222
end
23-
real function f2(x)
23+
real function s2f2(x)
2424
real :: x(10)
2525
end
2626
end interface

flang/test/Semantics/resolve67.f90

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ real function plus(x)
8989
end
9090
end interface
9191
interface operator(.not.)
92+
!WARNING: The external interface 'not1' is not compatible with an earlier definition (distinct numbers of dummy arguments)
9293
real function not1(x)
9394
real, value :: x
9495
end

0 commit comments

Comments
 (0)