diff --git a/flang/lib/Evaluate/character.h b/flang/lib/Evaluate/character.h --- a/flang/lib/Evaluate/character.h +++ b/flang/lib/Evaluate/character.h @@ -106,6 +106,7 @@ static Character REPEAT(const Character &str, ConstantSubscript ncopies) { Character result; if (!str.empty()) { + result.reserve(ncopies * str.size()); while (ncopies-- > 0) { result += str; } diff --git a/flang/lib/Evaluate/fold-character.cpp b/flang/lib/Evaluate/fold-character.cpp --- a/flang/lib/Evaluate/fold-character.cpp +++ b/flang/lib/Evaluate/fold-character.cpp @@ -97,9 +97,16 @@ } else if (name == "repeat") { // not elemental if (auto scalars{GetScalarConstantArguments( context, funcRef.arguments())}) { - return Expr{Constant{ - CharacterUtils::REPEAT(std::get>(*scalars), - std::get>(*scalars).ToInt64())}}; + auto str{std::get>(*scalars)}; + auto n{std::get>(*scalars).ToInt64()}; + if (static_cast(n) * str.size() > + (1 << 20)) { // sanity limit of 1MiB + context.messages().Say( + "Result of REPEAT() is too large to compute at compilation time (%g characters)"_port_en_US, + static_cast(n) * str.size()); + } else { + return Expr{Constant{CharacterUtils::REPEAT(str, n)}}; + } } } else if (name == "trim") { // not elemental if (auto scalar{ diff --git a/flang/test/Evaluate/errors01.f90 b/flang/test/Evaluate/errors01.f90 --- a/flang/test/Evaluate/errors01.f90 +++ b/flang/test/Evaluate/errors01.f90 @@ -137,6 +137,10 @@ !CHERK: error: Must be a constant value integer, parameter :: bad2 = storage_size(y) end subroutine + subroutine s13 + !CHECK: portability: Result of REPEAT() is too large to compute at compilation time (1.1259e+15 characters) + print *, repeat(repeat(' ', 2**20), 2**30) + end subroutine subroutine warnings real, parameter :: ok1 = scale(0.0, 99999) ! 0.0 real, parameter :: ok2 = scale(1.0, -99999) ! 0.0