diff --git a/flang/docs/Extensions.md b/flang/docs/Extensions.md --- a/flang/docs/Extensions.md +++ b/flang/docs/Extensions.md @@ -134,6 +134,8 @@ bound, in a scope with IMPLICIT NONE(TYPE) if the name of the dummy argument would have caused it to be implicitly typed as default INTEGER if IMPLICIT NONE(TYPE) were absent. +* OPEN(ACCESS='APPEND') is interpreted as OPEN(POSITION='APPEND') + to ease porting from Sun Fortran. ### Extensions supported when enabled by options diff --git a/flang/include/flang/Common/Fortran-features.h b/flang/include/flang/Common/Fortran-features.h --- a/flang/include/flang/Common/Fortran-features.h +++ b/flang/include/flang/Common/Fortran-features.h @@ -30,7 +30,7 @@ EquivalenceNumericWithCharacter, AdditionalIntrinsics, AnonymousParents, OldLabelDoEndStatements, LogicalIntegerAssignment, EmptySourceFile, ProgramReturn, ImplicitNoneTypeNever, ImplicitNoneTypeAlways, - ForwardRefDummyImplicitNone) + ForwardRefDummyImplicitNone, OpenAccessAppend) using LanguageFeatures = EnumSet; diff --git a/flang/lib/Semantics/check-io.cpp b/flang/lib/Semantics/check-io.cpp --- a/flang/lib/Semantics/check-io.cpp +++ b/flang/lib/Semantics/check-io.cpp @@ -831,9 +831,16 @@ {IoSpecKind::Convert, {"BIG_ENDIAN", "LITTLE_ENDIAN", "NATIVE"}}, {IoSpecKind::Dispose, {"DELETE", "KEEP"}}, }; - if (!specValues.at(specKind).count(parser::ToUpperCaseLetters(value))) { - context_.Say(source, "Invalid %s value '%s'"_err_en_US, - parser::ToUpperCaseLetters(common::EnumToString(specKind)), value); + auto upper{parser::ToUpperCaseLetters(value)}; + if (specValues.at(specKind).count(upper) == 0) { + if (specKind == IoSpecKind::Access && upper == "APPEND" && + context_.languageFeatures().ShouldWarn( + common::LanguageFeature::OpenAccessAppend)) { + context_.Say(source, "ACCESS='%s' interpreted as POSITION='%s'"_en_US, value, upper); + } else { + context_.Say(source, "Invalid %s value '%s'"_err_en_US, + parser::ToUpperCaseLetters(common::EnumToString(specKind)), value); + } } } diff --git a/flang/runtime/io-api.cpp b/flang/runtime/io-api.cpp --- a/flang/runtime/io-api.cpp +++ b/flang/runtime/io-api.cpp @@ -589,7 +589,8 @@ io.GetIoErrorHandler().Crash( "SetAccess() called when not in an OPEN statement"); } - static const char *keywords[]{"SEQUENTIAL", "DIRECT", "STREAM", nullptr}; + static const char *keywords[]{ + "SEQUENTIAL", "DIRECT", "STREAM", "APPEND", nullptr}; switch (IdentifyValue(keyword, length, keywords)) { case 0: open->set_access(Access::Sequential); @@ -600,6 +601,9 @@ case 2: open->set_access(Access::Stream); break; + case 3: // Sun Fortran extension ACCESS=APPEND: treat as if POSITION=APPEND + open->set_position(Position::Append); + break; default: open->SignalError(IostatErrorInKeyword, "Invalid ACCESS='%.*s'", static_cast(length), keyword);