Skip to content

Commit e75fda1

Browse files
authored
[flang] Acknowledge non-enforcement of C7108 (#139169)
Fortran 2023 constraint C7108 prohibits the use of a structure constructor in a way that is ambiguous with a generic function reference (intrinsic or user-defined). Sadly, no Fortran compiler implements this constraint, and the common portable interpretation seems to be the generic resolution, not the structure constructor. Restructure the processing of structure constructors in expression analysis so that it can be driven both from the parse tree as well as from generic resolution, and then use it to detect ambigous structure constructor / generic function cases, so that a portability warning can be issued. And document this as a new intentional violation of the standard in Extensions.md. Fixes #138807.
1 parent 2ca2e1c commit e75fda1

File tree

10 files changed

+340
-187
lines changed

10 files changed

+340
-187
lines changed

flang/docs/Extensions.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,11 @@ end
159159
to be constant will generate a compilation error. `ieee_support_standard`
160160
depends in part on `ieee_support_halting`, so this also applies to
161161
`ieee_support_standard` calls.
162+
* F'2023 constraint C7108 prohibits the use of a structure constructor
163+
that could also be interpreted as a generic function reference.
164+
No other Fortran compiler enforces C7108 (to our knowledge);
165+
they all resolve the ambiguity by interpreting the call as a function
166+
reference. We do the same, with a portability warning.
162167

163168
## Extensions, deletions, and legacy features supported by default
164169

flang/include/flang/Semantics/expression.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -394,6 +394,19 @@ class ExpressionAnalyzer {
394394
MaybeExpr AnalyzeComplex(MaybeExpr &&re, MaybeExpr &&im, const char *what);
395395
std::optional<Chevrons> AnalyzeChevrons(const parser::CallStmt &);
396396

397+
// CheckStructureConstructor() is used for parsed structure constructors
398+
// as well as for generic function references.
399+
struct ComponentSpec {
400+
ComponentSpec() = default;
401+
ComponentSpec(ComponentSpec &&) = default;
402+
parser::CharBlock source, exprSource;
403+
bool hasKeyword{false};
404+
const Symbol *keywordSymbol{nullptr};
405+
MaybeExpr expr;
406+
};
407+
MaybeExpr CheckStructureConstructor(parser::CharBlock typeName,
408+
const semantics::DerivedTypeSpec &, std::list<ComponentSpec> &&);
409+
397410
MaybeExpr IterativelyAnalyzeSubexpressions(const parser::Expr &);
398411

399412
semantics::SemanticsContext &context_;

flang/include/flang/Support/Fortran-features.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,8 @@ ENUM_CLASS(LanguageFeature, BackslashEscapes, OldDebugLines,
5454
PolymorphicActualAllocatableOrPointerToMonomorphicDummy, RelaxedPureDummy,
5555
UndefinableAsynchronousOrVolatileActual, AutomaticInMainProgram, PrintCptr,
5656
SavedLocalInSpecExpr, PrintNamelist, AssumedRankPassedToNonAssumedRank,
57-
IgnoreIrrelevantAttributes, Unsigned, ContiguousOkForSeqAssociation)
57+
IgnoreIrrelevantAttributes, Unsigned, AmbiguousStructureConstructor,
58+
ContiguousOkForSeqAssociation)
5859

5960
// Portability and suspicious usage warnings
6061
ENUM_CLASS(UsageWarning, Portability, PointerToUndefinable,

flang/lib/Semantics/expression.cpp

Lines changed: 269 additions & 185 deletions
Large diffs are not rendered by default.

flang/lib/Support/Fortran-features.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ LanguageFeatureControl::LanguageFeatureControl() {
4545
warnLanguage_.set(LanguageFeature::HollerithPolymorphic);
4646
warnLanguage_.set(LanguageFeature::ListDirectedSize);
4747
warnLanguage_.set(LanguageFeature::IgnoreIrrelevantAttributes);
48+
warnLanguage_.set(LanguageFeature::AmbiguousStructureConstructor);
4849
warnUsage_.set(UsageWarning::ShortArrayActual);
4950
warnUsage_.set(UsageWarning::FoldingException);
5051
warnUsage_.set(UsageWarning::FoldingAvoidsRuntimeCrash);

flang/test/Semantics/c7108.f90

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
! RUN: %python %S/test_errors.py %s %flang_fc1 -pedantic -Werror
2+
! F'2023 C7108 is portably unenforced.
3+
module m
4+
type foo
5+
integer n
6+
end type
7+
interface foo
8+
procedure bar0, bar1, bar2, bar3
9+
end interface
10+
contains
11+
type(foo) function bar0(n)
12+
integer, intent(in) :: n
13+
print *, 'bar0'
14+
bar0%n = n
15+
end
16+
type(foo) function bar1()
17+
print *, 'bar1'
18+
bar1%n = 1
19+
end
20+
type(foo) function bar2(a)
21+
real, intent(in) :: a
22+
print *, 'bar2'
23+
bar2%n = a
24+
end
25+
type(foo) function bar3(L)
26+
logical, intent(in) :: L
27+
print *, 'bar3'
28+
bar3%n = merge(4,5,L)
29+
end
30+
end
31+
32+
program p
33+
use m
34+
type(foo) x
35+
x = foo(); print *, x ! ok, not ambiguous
36+
!PORTABILITY: Reference to generic function 'foo' (resolving to specific 'bar0') is ambiguous with a structure constructor of the same name
37+
x = foo(2); print *, x ! ambigous
38+
!PORTABILITY: Reference to generic function 'foo' (resolving to specific 'bar2') is ambiguous with a structure constructor of the same name
39+
x = foo(3.); print *, x ! ambiguous due to data conversion
40+
x = foo(.true.); print *, x ! ok, not ambigous
41+
end

flang/test/Semantics/generic09.f90

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
! RUN: %flang_fc1 -fdebug-unparse %s 2>&1 | FileCheck %s
2+
23
module m1
34
type foo
45
integer n
@@ -32,6 +33,9 @@ type(foo) function f2(a)
3233
end
3334
end
3435

36+
!CHECK: portability: Reference to generic function 'foo' (resolving to specific 'f1') is ambiguous with a structure constructor of the same name
37+
!CHECK: portability: Reference to generic function 'foo' (resolving to specific 'f2') is ambiguous with a structure constructor of the same name
38+
3539
program main
3640
use m3
3741
type(foo) x

flang/test/Semantics/resolve11.f90

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,8 @@ subroutine s4
6666
!ERROR: 'fun' is PRIVATE in 'm4'
6767
use m4, only: foo, fun
6868
type(foo) x ! ok
69-
print *, foo() ! ok
69+
!PORTABILITY: Reference to generic function 'foo' (resolving to specific 'fun') is ambiguous with a structure constructor of the same name
70+
print *, foo()
7071
end
7172

7273
module m5

flang/test/Semantics/resolve17.f90

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,7 @@ module m14d
290290
contains
291291
subroutine test
292292
real :: y
293+
!PORTABILITY: Reference to generic function 'foo' (resolving to specific 'bar') is ambiguous with a structure constructor of the same name
293294
y = foo(1.0)
294295
x = foo(2)
295296
end subroutine
@@ -301,6 +302,7 @@ module m14e
301302
contains
302303
subroutine test
303304
real :: y
305+
!PORTABILITY: Reference to generic function 'foo' (resolving to specific 'bar') is ambiguous with a structure constructor of the same name
304306
y = foo(1.0)
305307
x = foo(2)
306308
end subroutine

flang/test/Semantics/resolve18.f90

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,7 @@ subroutine s_21_23
348348
use m21
349349
use m23
350350
type(foo) x ! Intel and NAG error
351+
!PORTABILITY: Reference to generic function 'foo' (resolving to specific 'f1') is ambiguous with a structure constructor of the same name
351352
print *, foo(1.) ! Intel error
352353
print *, foo(1.,2.,3.) ! Intel error
353354
call ext(foo) ! GNU and Intel error

0 commit comments

Comments
 (0)