英文:
Using function result as character length in Fortran
问题
Fortran标准允许在自动分配中使用函数的结果来声明字符长度。这意味着在如下的代码行中使用函数f
的结果来定义字符变量r
的长度是有效的:
character(len=this%f())::r
这在Fortran中是合法的用法。因此,GNU编译器的错误报告可能是一个编译器错误,而不是Fortran标准的问题。其他编译器,如Intel和Nvidia,成功编译了这段代码,这表明这种用法在它们的编译器中是有效的,而不是一个错误。这可能是编译器的实现差异导致的问题。
英文:
Consider the following minimal working example:
module lib
type t
contains
procedure::f,g
end type
contains
integer function f(this)
class(t),intent(in)::this
f=10
end
function g(this)result(r)
class(t),intent(in)::this
character(len=this%f())::r
r='42'
end
end
program prog
use lib
type(t)::o
print*,o%g()
end
Compiling this code with the GNU (gfortran 11.1.0) compiler leads to the following message:
f951: internal compiler error: Segmentation fault
0x16463d7 internal_error(char const*, ...)
???:0
0x64b47c gfc_find_derived_vtab(gfc_symbol*)
???:0
0x672605 gfc_reduce_init_expr(gfc_expr*)
???:0
0x6572e3 gfc_match_char_spec(gfc_typespec*)
???:0
0x65e227 gfc_match_decl_type_spec(gfc_typespec*, int)
???:0
0x65f93c gfc_match_data_decl()
???:0
0x6d6236 gfc_parse_file()
???:0
Please submit a full bug report
The message says that it is a compiler bug, but I am not so sure. The NAG (nagfor 7.1) compiler also fails to compile the code with Error: line 13: Reference to non-specification function F in specification expression
. However, the Intel (ifort 2021.8.0, ifx 2023.0.0) and Nvidia (nvfortran 22.9) compilers compile the code successfully. The problem in the first two compilers (GNU and NAG) is caused by the line character(len=this%f())::r
.
Does Fortran standard allow declaration of the character length (in the automatic allocation) with the result of a function (here f
)? Is it a bug of the GNU compiler or a feature of the Intel and Nvidia compilers?
答案1
得分: 2
以下是翻译好的部分:
Some functions can be used to give the length of a character function result; the particular function used here cannot.
一些函数可以用来获取字符函数结果的长度;这里使用的特定函数则不能。
First: compilers shouldn't crash. What you see with gfortran is an internal compiler error (ICE), a bug. ICEs are bugs whether the code presented is valid Fortran or not. 1
首先,编译器不应崩溃。您在gfortran中看到的是内部编译器错误(ICE),这是一个错误。无论所呈现的代码是否是有效的Fortran,ICE都是错误。1
The terminology introduced by the NAG compiler in rejecting your code is key to whether a function is allowed to be used. The length of a character function result must be a specification expression. 2 The rules around how a specification expression is made are fairly involved (see Fortran 2018 10.1.11 and other questions and answers here for more detail) but the reason F
here is rejected by nagfor is that F
is not a pure function.
NAG编译器在拒绝您的代码时引入的术语是确定是否允许使用函数的关键。字符函数结果的长度必须是一个“规范表达式”。2 关于如何创建规范表达式的规则相当复杂(有关更多详细信息,请参见Fortran 2018 10.1.11和其他问题及答案),但nagfor拒绝F
的原因是F
不是一个“纯”函数。
For F
to be a specification function it must be pure (F2018 10.1.11 Note 1):
要使F
成为规范函数,它必须是纯粹的(F2018 10.1.11附注1):
The requirement that they be pure ensures that they cannot have side effects that could affect other objects being declared in the same specification-part.
要求它们是纯粹的,以确保它们不会产生可能影响同一规范部分中声明的其他对象的副作用。
At least with the version of gfortran I tested, you can work around the ICE, once you've made F
pure, by changing the specification expression to:
至少根据我测试的gfortran版本,一旦您将F
设为纯粹,就可以绕过ICE,方法是将规范表达式更改为:
character(len=f(this))::r
Finally, note that one cannot confidently say the Intel/NVIDIA compilers are wrong to accept this code. The code is not valid Fortran so a compiler can chose to do anything, including accept it as an extension. This isn't a case where a compiler is required to be able to diagnose your error. (One could still call it a compiler bug as this particular violation may well be good to diagnose and easy to see.)
最后,请注意不能确定Intel/NVIDIA编译器接受此代码是否正确。这段代码不是有效的Fortran代码,因此编译器可以选择执行任何操作,包括将其视为扩展功能。这不是编译器必须能够诊断您的错误的情况。 (可以称之为编译器错误,因为这种特定的违规可能很容易诊断和看到。)
1 这并不真正正确。如果代码不是有效的Fortran,那么编译器允许采取任何响应措施(只要它能够报告必须能够检测和报告的不足)。崩溃是允许的操作,尽管通常编译器供应商都认为ICE是一个错误,即使它是Fortran标准下允许的响应,也会导致用户体验较差。
2 这同样适用于数组界限和更广泛的过程的自动数据对象。
英文:
Some functions can be used to give the length of a character function result; the particular function used here cannot.
First: compilers shouldn't crash. What you see with gfortran is an internal compiler error (ICE), a bug. ICEs are bugs whether the code presented is valid Fortran or not.<sup>1</sup>
The terminology introduced by the NAG compiler in rejecting your code is key to whether a function is allowed to be used. The length of a character function result must be a specification expression.<sup>2</sup> The rules around how a specification expression is made are fairly involved (see Fortran 2018 10.1.11 and other questions and answers here for more detail) but the reason F
here is rejected by nagfor is that F
is not a pure function.
For F
to be a specification function it must be pure (F2018 10.1.11 Note 1):
> The requirement that they be pure ensures that they cannot have side effects
that could affect other objects being declared in the same specification-part.
At least with the version of gfortran I tested, you can work around the ICE, once you've made F
pure, by changing the specification expression to:
character(len=f(this))::r
Finally, note that one cannot confidently say the Intel/NVIDIA compilers are wrong to accept this code. The code is not valid Fortran so a compiler can chose to do anything, including accept it as an extension. This isn't a case where a compiler is required to be able to diagnose your error. (One could still call it a compiler bug as this particular violation may well be good to diagnose and easy to see.)
<sup>1</sup> This isn't really true. If the code is not valid Fortran then the compiler is allowed to do anything in response (as long as it is capable of reporting those deficiencies it is required to be able to detect and report). Crashing is a thing it's allowed to do, although compiler vendors generally accept that an ICE is a bug even if it's an allowed response under the Fortran standard: it's a poor user experience.
<sup>2</sup> This applies equally to array bounds and to automatic data objects of a procedure more widely.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论