The standard requires a compiler to diagnose an incorrect use of a pointer in a DEALLOCATE statement. The pointer must be associated with an entire object that was allocated as a pointer (not allocatable) by an ALLOCATE statement. Implement by appending a validation footer to pointer allocations. This is an extra allocated word that encodes the base address of the allocation. If it is not found after the data payload when the pointer is deallocated, signal an error. There is a chance of a false positive result, but that should be vanishingly unlikely. This change requires all pointer allocations (not allocatables) to take place in the runtime in PointerAllocate(), which might be slower in cases that could otherwise be handled with a native memory allocation operation. I believe that memory allocation of pointers is less common than with allocatables, which are not affected. If this turns out to become a performance problem, we can inline the creation and initialization of the footer word. Fixes https://github.com/llvm/llvm-project/issues/78391.
63 lines
2.4 KiB
C++
63 lines
2.4 KiB
C++
//===-- runtime/stat.h ------------------------------------------*- C++ -*-===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Defines the values returned by the runtime for STAT= specifiers
|
|
// on executable statements.
|
|
|
|
#ifndef FORTRAN_RUNTIME_STAT_H_
|
|
#define FORTRAN_RUNTIME_STAT_H_
|
|
#include "flang/ISO_Fortran_binding_wrapper.h"
|
|
#include "flang/Runtime/api-attrs.h"
|
|
#include "flang/Runtime/magic-numbers.h"
|
|
namespace Fortran::runtime {
|
|
|
|
class Descriptor;
|
|
class Terminator;
|
|
|
|
// The value of STAT= is zero when no error condition has arisen.
|
|
|
|
enum Stat {
|
|
StatOk = 0, // required to be zero by Fortran
|
|
|
|
// Interoperable STAT= codes
|
|
StatBaseNull = CFI_ERROR_BASE_ADDR_NULL,
|
|
StatBaseNotNull = CFI_ERROR_BASE_ADDR_NOT_NULL,
|
|
StatInvalidElemLen = CFI_INVALID_ELEM_LEN,
|
|
StatInvalidRank = CFI_INVALID_RANK,
|
|
StatInvalidType = CFI_INVALID_TYPE,
|
|
StatInvalidAttribute = CFI_INVALID_ATTRIBUTE,
|
|
StatInvalidExtent = CFI_INVALID_EXTENT,
|
|
StatInvalidDescriptor = CFI_INVALID_DESCRIPTOR,
|
|
StatMemAllocation = CFI_ERROR_MEM_ALLOCATION,
|
|
StatOutOfBounds = CFI_ERROR_OUT_OF_BOUNDS,
|
|
|
|
// Standard STAT= values
|
|
StatFailedImage = FORTRAN_RUNTIME_STAT_FAILED_IMAGE,
|
|
StatLocked = FORTRAN_RUNTIME_STAT_LOCKED,
|
|
StatLockedOtherImage = FORTRAN_RUNTIME_STAT_LOCKED_OTHER_IMAGE,
|
|
StatMissingEnvVariable = FORTRAN_RUNTIME_STAT_MISSING_ENV_VAR,
|
|
StatStoppedImage = FORTRAN_RUNTIME_STAT_STOPPED_IMAGE,
|
|
StatUnlocked = FORTRAN_RUNTIME_STAT_UNLOCKED,
|
|
StatUnlockedFailedImage = FORTRAN_RUNTIME_STAT_UNLOCKED_FAILED_IMAGE,
|
|
|
|
// Additional "processor-defined" STAT= values
|
|
StatInvalidArgumentNumber = FORTRAN_RUNTIME_STAT_INVALID_ARG_NUMBER,
|
|
StatMissingArgument = FORTRAN_RUNTIME_STAT_MISSING_ARG,
|
|
StatValueTooShort = FORTRAN_RUNTIME_STAT_VALUE_TOO_SHORT,
|
|
StatMoveAllocSameAllocatable =
|
|
FORTRAN_RUNTIME_STAT_MOVE_ALLOC_SAME_ALLOCATABLE,
|
|
StatBadPointerDeallocation = FORTRAN_RUNTIME_STAT_BAD_POINTER_DEALLOCATION,
|
|
};
|
|
|
|
RT_API_ATTRS const char *StatErrorString(int);
|
|
RT_API_ATTRS int ToErrmsg(const Descriptor *errmsg, int stat); // returns stat
|
|
RT_API_ATTRS int ReturnError(Terminator &, int stat,
|
|
const Descriptor *errmsg = nullptr, bool hasStat = false);
|
|
} // namespace Fortran::runtime
|
|
#endif // FORTRAN_RUNTIME_STAT_H
|