Skip to content

Commit af964c7

Browse files
authored
[flang][runtime] Let FORT_CHECK_POINTER_DEALLOCATION=0 disable runtime … (#84956)
…check Add an environment variable by which a user can disable the pointer validation check in DEALLOCATE statement handling. This is not safe, but it can help make a code work that allocates a pointer with an extended derived type, associates its target with a pointer to one of its ancestor types, and then deallocates that pointer.
1 parent 5661188 commit af964c7

File tree

5 files changed

+87
-11
lines changed

5 files changed

+87
-11
lines changed

flang/docs/RuntimeEnvironment.md

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
<!--===- docs/RuntimeEnvironment.md
2+
3+
Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
See https://llvm.org/LICENSE.txt for license information.
5+
SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
7+
-->
8+
9+
```{contents}
10+
---
11+
local:
12+
---
13+
```
14+
15+
# Environment variables of significance to Fortran execution
16+
17+
A few environment variables are queried by the Fortran runtime support
18+
library.
19+
20+
The following environment variables can affect the behavior of
21+
Fortran programs during execution.
22+
23+
## `DEFAULT_UTF8=1`
24+
25+
Set `DEFAULT_UTF8` to cause formatted external input to assume UTF-8
26+
encoding on input and use UTF-8 encoding on formatted external output.
27+
28+
## `FORT_CONVERT`
29+
30+
Determines data conversions applied to unformatted I/O.
31+
32+
* `NATIVE`: no conversions (default)
33+
* `LITTLE_ENDIAN`: assume input is little-endian; emit little-endian output
34+
* `BIG_ENDIAN`: assume input is big-endian; emit big-endian output
35+
* `SWAP`: reverse endianness (always convert)
36+
37+
## `FORT_CHECK_POINTER_DEALLOCATION`
38+
39+
Fortran requires that a pointer that appears in a `DEALLOCATE` statement
40+
must have been allocated in an `ALLOCATE` statement with the same declared
41+
type.
42+
The runtime support library validates this requirement by checking the
43+
size of the allocated data, and will fail with an error message if
44+
the deallocated pointer is not valid.
45+
Set `FORT_CHECK_POINTER_DEALLOCATION=0` to disable this check.
46+
47+
## `FORT_FMT_RECL`
48+
49+
Set to an integer value to specify the record length for list-directed
50+
and `NAMELIST` output.
51+
The default is 72.
52+
53+
## `NO_STOP_MESSAGE`
54+
55+
Set `NO_STOP_MESSAGE=1` to disable the extra information about
56+
IEEE floating-point exception flags that the Fortran language
57+
standard requires for `STOP` and `ERROR STOP` statements.

flang/docs/index.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ on how to get in touch with us and to learn more about the current status.
8080
Preprocessing
8181
ProcedurePointer
8282
RuntimeDescriptor
83+
RuntimeEnvironment
8384
RuntimeTypeInfo
8485
Semantics
8586
f2018-grammar.md

flang/runtime/environment.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,19 @@ void ExecutionEnvironment::Configure(int ac, const char *av[],
123123
}
124124
}
125125

126+
if (auto *x{std::getenv("FORT_CHECK_POINTER_DEALLOCATION")}) {
127+
char *end;
128+
auto n{std::strtol(x, &end, 10)};
129+
if (n >= 0 && n <= 1 && *end == '\0') {
130+
checkPointerDeallocation = n != 0;
131+
} else {
132+
std::fprintf(stderr,
133+
"Fortran runtime: FORT_CHECK_POINTER_DEALLOCATION=%s is invalid; "
134+
"ignored\n",
135+
x);
136+
}
137+
}
138+
126139
// TODO: Set RP/ROUND='PROCESSOR_DEFINED' from environment
127140
}
128141

flang/runtime/environment.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ struct ExecutionEnvironment {
4848
Convert conversion{Convert::Unknown}; // FORT_CONVERT
4949
bool noStopMessage{false}; // NO_STOP_MESSAGE=1 inhibits "Fortran STOP"
5050
bool defaultUTF8{false}; // DEFAULT_UTF8
51+
bool checkPointerDeallocation{true}; // FORT_CHECK_POINTER_DEALLOCATION
5152
};
5253

5354
extern ExecutionEnvironment executionEnvironment;

flang/runtime/pointer.cpp

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include "flang/Runtime/pointer.h"
1010
#include "assign-impl.h"
1111
#include "derived.h"
12+
#include "environment.h"
1213
#include "stat.h"
1314
#include "terminator.h"
1415
#include "tools.h"
@@ -184,17 +185,20 @@ int RTDEF(PointerDeallocate)(Descriptor &pointer, bool hasStat,
184185
if (!pointer.IsAllocated()) {
185186
return ReturnError(terminator, StatBaseNull, errMsg, hasStat);
186187
}
187-
// Validate the footer. This should fail if the pointer doesn't
188-
// span the entire object, or the object was not allocated as a
189-
// pointer.
190-
std::size_t byteSize{pointer.Elements() * pointer.ElementBytes()};
191-
constexpr std::size_t align{sizeof(std::uintptr_t)};
192-
byteSize = ((byteSize + align - 1) / align) * align;
193-
void *p{pointer.raw().base_addr};
194-
std::uintptr_t *footer{
195-
reinterpret_cast<std::uintptr_t *>(static_cast<char *>(p) + byteSize)};
196-
if (*footer != ~reinterpret_cast<std::uintptr_t>(p)) {
197-
return ReturnError(terminator, StatBadPointerDeallocation, errMsg, hasStat);
188+
if (executionEnvironment.checkPointerDeallocation) {
189+
// Validate the footer. This should fail if the pointer doesn't
190+
// span the entire object, or the object was not allocated as a
191+
// pointer.
192+
std::size_t byteSize{pointer.Elements() * pointer.ElementBytes()};
193+
constexpr std::size_t align{sizeof(std::uintptr_t)};
194+
byteSize = ((byteSize + align - 1) / align) * align;
195+
void *p{pointer.raw().base_addr};
196+
std::uintptr_t *footer{
197+
reinterpret_cast<std::uintptr_t *>(static_cast<char *>(p) + byteSize)};
198+
if (*footer != ~reinterpret_cast<std::uintptr_t>(p)) {
199+
return ReturnError(
200+
terminator, StatBadPointerDeallocation, errMsg, hasStat);
201+
}
198202
}
199203
return ReturnError(terminator,
200204
pointer.Destroy(/*finalize=*/true, /*destroyPointers=*/true, &terminator),

0 commit comments

Comments
 (0)