(j3.2006) 5.4.7p2 goes a little bit too far
Van Snyder
Van.Snyder
Fri Jul 19 22:02:11 EDT 2013
5.4.7p2 says:
"If a nonpointer object has default initialization, it shall not appear
in a <data-stmt-object-list>."
I suspect we didn't intend to prohibit this program, which all of my
processors accept and produce what I expect:
type :: T
integer :: I = 3
real :: R = 42.0
end type
type(t), parameter :: P = T()
integer :: A(p%i), I
data (a(i), i = 1, p%i) / 1, 2, 3 /
! This---------------^^^ is "in a <data-stmt-object-list>"
print *, a
end
Perhaps 5.4.7p2 ought to be
"If a nonpointer variable has default initialization, it shall not
appear in a <data-stmt-object-list>."
F08/0062 established that it would be onerous to require a processor to
initialize part of an object using default initialization and part using
explicit initialization in a DATA statement. I interpreted this to mean
"some components of...," not "some array elements of...," since that's
how Tobias posed the question. A question Tobias didn't ask was whether
we intended to prohibit this:
type(t) :: B(3)
data B(2) / t(2,39.0) /
which doesn't impose the burden contemplated by F08/0062.
It is the same as (but less wordy than)
type(t) :: B(3) = [ t(), t(2,39.0), t() ]
which is explicitly allowed by 5.2.3p1.
To remove this inconsistency, while preserving consistency with
F08/0062, it would be desirable if 5.4.7p2 were
"If a variable has default initialization, a subcomponent of that
variable shall not appear in a <data-stmt-object-list>."
(notice that "nonpointer" is no longer necessary) or
"If a type has default initialization, a subcomponent of a variable of
that type shall not appear in a <data-stmt-object-list>."
This is, after all, the reasoning behind the answer to F08/0062. Some
minor work would also be needed in 5.2.3p1.
I believe the former could reasonably be addressed by an interpretation
("did we mean 'object' or 'variable?'"). The latter might be considered
to be a feature request, and therefore not an appropriate subject for an
interpretation, unless the question "did we mean 'object' or
'subcomponent of a variable?'" is not out of order.
Since we have decided to sit on our hands for seven years or so, there
is a good chance will not address such trivial irritations any time
soon, if ever.
5.7.4p2 caused a problem in a situation where I needed to initialize
most of an array to values specified by default initialization, and a
relatively smaller (but not small) subset to other values. The
subscripts of the interesting elements are given by named constants,
which are generated by another processor. It therefore makes for a very
fragile program if I look up the values of those constants in the output
of that processor and create an initialization of the form
type(t) :: B(first:last) = [ t(), t(2,39.0), t(), ... ]
or a hairier mess involving named constants if the initialization is so
long that it won't fit in one statement. If I change the input to the
program that generates the named constants, this kind of initialization
silently produces the wrong answer.
The program would be much less fragile if I could have written
type(t) :: B(first:last)
data B(an_interesting_one) / t(2,39.0) /
data B ...
I can't remove the default initialization and do
type(t) :: B(first:last) = t(3,42.0)
data B(an_interesting_one) / t(2,39.0) /
data B ...
because that falls afoul of 5.2.3p1.
I don't know apriori the numeric order of the interesting subscripts, so
the program is only marginally less fragile, and rather more expensive
to maintain, if I sort the named constants into numeric order, remove
default initialization and do
type(t) :: B(first:last)
integer, parameter :: n1 = first_interesting_one - first
data ( b(i), i = first, first_interesting_one-1 ) / n1*t(3,42.0) /
data b(first_interesting_one) / t(2,39.0) /
integer, parameter :: n2 = second_interesting_one - first_interesting_one - 1
data ( b(i), i = first_interesting_one+1, second_interesting_one-1 ) &
& / n2*t(3,42.0) /
...
The somewhat dissatisfying solution I adopted was the following:
type(t) :: B(first:last)
logical, save :: FirstTime = .true.
if ( firstTime ) then
firstTime = .false.
b(an_interesting_one) = t(2,39.)
b(another_interesting_one) = ...
...
end if
What was even more irritating, and expensive and embarrassing, was that
some of my processors were perfectly happy to accept what I had naively
hoped would work, i.e., perfectly happy to ignore 5.4.7p2 because it's
not a constraint. I didn't get my ass bitten until one of my clients
complained that my code wouldn't compile.
More information about the J3
mailing list