Skip to content

Commit 9d33874

Browse files
authored
[flang] Support -f[no-]realloc-lhs. (#120165)
-frealloc-lhs is the default. If -fno-realloc-lhs is specified, then an allocatable on the left side of an intrinsic assignment is not implicitly (re)allocated to conform with the right hand side. Fortran runtime will issue an error if there is a mismatch in shape/type/allocation-status.
1 parent 525c818 commit 9d33874

File tree

8 files changed

+72
-3
lines changed

8 files changed

+72
-3
lines changed

clang/include/clang/Driver/Options.td

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3463,6 +3463,9 @@ defm diagnostics_show_line_numbers : BoolFOption<"diagnostics-show-line-numbers"
34633463
NegFlag<SetFalse, [], [ClangOption, CC1Option],
34643464
"Show line numbers in diagnostic code snippets">,
34653465
PosFlag<SetTrue>>;
3466+
def fno_realloc_lhs : Flag<["-"], "fno-realloc-lhs">, Group<f_Group>,
3467+
HelpText<"An allocatable left-hand side of an intrinsic assignment is assumed to be allocated and match the shape/type of the right-hand side">,
3468+
Visibility<[FlangOption, FC1Option]>;
34663469
def fno_stack_protector : Flag<["-"], "fno-stack-protector">, Group<f_Group>,
34673470
HelpText<"Disable the use of stack protectors">;
34683471
def fno_strict_aliasing : Flag<["-"], "fno-strict-aliasing">, Group<f_Group>,
@@ -4296,6 +4299,9 @@ defm stack_size_section : BoolFOption<"stack-size-section",
42964299
PosFlag<SetTrue, [], [ClangOption, CC1Option],
42974300
"Emit section containing metadata on function stack sizes">,
42984301
NegFlag<SetFalse>>;
4302+
def frealloc_lhs : Flag<["-"], "frealloc-lhs">, Group<f_Group>,
4303+
Visibility<[FlangOption, FC1Option]>,
4304+
HelpText<"If an allocatable left-hand side of an intrinsic assignment is unallocated or its shape/type does not match the right-hand side, then it is automatically (re)allocated">;
42994305
def fstack_usage : Flag<["-"], "fstack-usage">, Group<f_Group>,
43004306
HelpText<"Emit .su file containing information on function stack sizes">;
43014307
def stack_usage_file : Separate<["-"], "stack-usage-file">,
@@ -6775,7 +6781,6 @@ defm real_4_real_8 : BooleanFFlag<"real-4-real-8">, Group<gfortran_Group>;
67756781
defm real_8_real_10 : BooleanFFlag<"real-8-real-10">, Group<gfortran_Group>;
67766782
defm real_8_real_16 : BooleanFFlag<"real-8-real-16">, Group<gfortran_Group>;
67776783
defm real_8_real_4 : BooleanFFlag<"real-8-real-4">, Group<gfortran_Group>;
6778-
defm realloc_lhs : BooleanFFlag<"realloc-lhs">, Group<gfortran_Group>;
67796784
defm recursive : BooleanFFlag<"recursive">, Group<gfortran_Group>;
67806785
defm repack_arrays : BooleanFFlag<"repack-arrays">, Group<gfortran_Group>;
67816786
defm second_underscore : BooleanFFlag<"second-underscore">, Group<gfortran_Group>;

clang/lib/Driver/ToolChains/Flang.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,9 @@ void Flang::addFortranDialectOptions(const ArgList &Args,
5555
options::OPT_fdefault_double_8,
5656
options::OPT_flarge_sizes,
5757
options::OPT_fno_automatic,
58-
options::OPT_fhermetic_module_files});
58+
options::OPT_fhermetic_module_files,
59+
options::OPT_frealloc_lhs,
60+
options::OPT_fno_realloc_lhs});
5961
}
6062

6163
void Flang::addPreprocessingOptions(const ArgList &Args,

flang/include/flang/Lower/LoweringOptions.def

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,5 +38,11 @@ ENUM_LOWERINGOPT(Underscoring, unsigned, 1, 1)
3838
/// (i.e. wraps around as two's complement). Off by default.
3939
ENUM_LOWERINGOPT(IntegerWrapAround, unsigned, 1, 0)
4040

41+
/// If true (default), follow Fortran 2003 rules for (re)allocating
42+
/// the allocatable on the left side of the intrinsic assignment,
43+
/// if LHS and RHS have mismatching shapes/types.
44+
/// If false, assume that the shapes/types/allocation-status match.
45+
ENUM_LOWERINGOPT(ReallocateLHS, unsigned, 1, 1)
46+
4147
#undef LOWERINGOPT
4248
#undef ENUM_LOWERINGOPT

flang/lib/Frontend/CompilerInvocation.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1378,6 +1378,11 @@ bool CompilerInvocation::createFromArgs(
13781378
invoc.getDiagnosticOpts().Remarks.push_back(a->getValue());
13791379
}
13801380

1381+
// -frealloc-lhs is the default.
1382+
if (!args.hasFlag(clang::driver::options::OPT_frealloc_lhs,
1383+
clang::driver::options::OPT_fno_realloc_lhs, true))
1384+
invoc.loweringOpts.setReallocateLHS(false);
1385+
13811386
success &= parseFrontendArgs(invoc.getFrontendOpts(), args, diags);
13821387
parseTargetArgs(invoc.getTargetOpts(), args);
13831388
parsePreprocessorArgs(invoc.getPreprocessorOpts(), args);

flang/lib/Lower/Bridge.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4461,7 +4461,8 @@ class FirConverter : public Fortran::lower::AbstractConverter {
44614461
// lowered.
44624462
const bool isWholeAllocatableAssignment =
44634463
!userDefinedAssignment && !isInsideHlfirWhere() &&
4464-
Fortran::lower::isWholeAllocatable(assign.lhs);
4464+
Fortran::lower::isWholeAllocatable(assign.lhs) &&
4465+
bridge.getLoweringOptions().getReallocateLHS();
44654466
const bool isUserDefAssignToPointerOrAllocatable =
44664467
userDefinedAssignment &&
44674468
firstDummyIsPointerOrAllocatable(*userDefinedAssignment);

flang/test/Driver/frealloc-lhs.f90

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
! Check that the driver passes through -f[no-]realloc-lhs:
2+
! RUN: %flang -### -S -frealloc-lhs %s -o - 2>&1 | FileCheck %s --check-prefix=ON
3+
! RUN: %flang -### -S -fno-realloc-lhs %s -o - 2>&1 | FileCheck %s --check-prefix=OFF
4+
5+
! Check that the compiler accepts -f[no-]realloc-lhs:
6+
! RUN: %flang_fc1 -emit-hlfir -frealloc-lhs %s -o -
7+
! RUN: %flang_fc1 -emit-hlfir -fno-realloc-lhs %s -o -
8+
9+
! ON: "-fc1"{{.*}}"-frealloc-lhs"
10+
11+
! OFF: "-fc1"{{.*}}"-fno-realloc-lhs"

flang/test/Lower/reallocate-lhs.f90

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
! RUN: bbc %s -o - -emit-hlfir | FileCheck %s --check-prefixes=ALL,REALLOCLHS
2+
! RUN: bbc %s -o - -emit-hlfir -frealloc-lhs | FileCheck %s --check-prefixes=ALL,REALLOCLHS
3+
! RUN: bbc %s -o - -emit-hlfir -frealloc-lhs=false | FileCheck %s --check-prefixes=ALL,NOREALLOCLHS
4+
! RUN: %flang_fc1 %s -o - -emit-hlfir | FileCheck %s --check-prefixes=ALL,REALLOCLHS
5+
! RUN: %flang_fc1 %s -o - -emit-hlfir -frealloc-lhs | FileCheck %s --check-prefixes=ALL,REALLOCLHS
6+
! RUN: %flang_fc1 %s -o - -emit-hlfir -fno-realloc-lhs | FileCheck %s --check-prefixes=ALL,NOREALLOCLHS
7+
8+
subroutine test1(a, b)
9+
integer, allocatable :: a(:), b(:)
10+
a = b + 1
11+
end
12+
13+
! ALL-LABEL: func.func @_QPtest1(
14+
! ALL: %[[VAL_3:.*]]:2 = hlfir.declare{{.*}}{fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFtest1Ea"}
15+
! REALLOCLHS: hlfir.assign %{{.*}} to %[[VAL_3]]#0 realloc : !hlfir.expr<?xi32>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>
16+
17+
! NOREALLOCLHS: %[[VAL_20:.*]] = fir.load %[[VAL_3]]#0 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>
18+
! NOREALLOCLHS: hlfir.assign %{{.*}} to %[[VAL_20]] : !hlfir.expr<?xi32>, !fir.box<!fir.heap<!fir.array<?xi32>>>
19+
20+
subroutine test2(a, b)
21+
character(len=*), allocatable :: a(:)
22+
character(len=*) :: b(:)
23+
a = b
24+
end subroutine test2
25+
26+
! ALL-LABEL: func.func @_QPtest2(
27+
! ALL: %[[VAL_3:.*]]:2 = hlfir.declare{{.*}}{fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFtest2Ea"}
28+
! REALLOCLHS: hlfir.assign %{{.*}} to %[[VAL_3]]#0 realloc keep_lhs_len : !fir.box<!fir.array<?x!fir.char<1,?>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.char<1,?>>>>>
29+
30+
! NOREALLOCLHS: %[[VAL_7:.*]] = fir.load %[[VAL_3]]#0 : !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.char<1,?>>>>>
31+
! NOREALLOCLHS: hlfir.assign %{{.*}} to %[[VAL_7]] : !fir.box<!fir.array<?x!fir.char<1,?>>>, !fir.box<!fir.heap<!fir.array<?x!fir.char<1,?>>>>
32+

flang/tools/bbc/bbc.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,12 @@ static llvm::cl::opt<bool> integerWrapAround(
234234
llvm::cl::desc("Treat signed integer overflow as two's complement"),
235235
llvm::cl::init(false));
236236

237+
static llvm::cl::opt<bool>
238+
reallocateLHS("frealloc-lhs",
239+
llvm::cl::desc("Follow Fortran 2003 rules for (re)allocating "
240+
"the LHS of the intrinsic assignment"),
241+
llvm::cl::init(true));
242+
237243
#define FLANG_EXCLUDE_CODEGEN
238244
#include "flang/Optimizer/Passes/CommandLineOpts.h"
239245
#include "flang/Optimizer/Passes/Pipelines.h"
@@ -375,6 +381,7 @@ static llvm::LogicalResult convertFortranSourceToMLIR(
375381
loweringOptions.setNoPPCNativeVecElemOrder(enableNoPPCNativeVecElemOrder);
376382
loweringOptions.setLowerToHighLevelFIR(useHLFIR || emitHLFIR);
377383
loweringOptions.setIntegerWrapAround(integerWrapAround);
384+
loweringOptions.setReallocateLHS(reallocateLHS);
378385
std::vector<Fortran::lower::EnvironmentDefault> envDefaults = {};
379386
Fortran::frontend::TargetOptions targetOpts;
380387
Fortran::frontend::CodeGenOptions cgOpts;

0 commit comments

Comments
 (0)