[flang] Warn about assumed-rank items in I/O lists (#182957)

An assumed-rank dummy argument is not a conforming I/O list or NAMELIST
group item. Add a -pedantic warning and some documentation.
This commit is contained in:
Peter Klausler 2026-02-26 06:59:49 -08:00 committed by GitHub
parent 1c2e9b1ea6
commit cbcaae2b5c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 46 additions and 6 deletions

View File

@ -483,6 +483,7 @@ end
are to the same value. Distinct initializations remain errors.
* A pointer component that has no default initialization or explicit value
in a structure constructor is defaulted to `NULL()`.
* An assumed-rank entity is an acceptable `NAMELIST` group item.
### Extensions supported when enabled by options

View File

@ -57,7 +57,7 @@ ENUM_CLASS(LanguageFeature, BackslashEscapes, OldDebugLines,
ForwardRefExplicitTypeDummy, InaccessibleDeferredOverride,
CudaWarpMatchFunction, DoConcurrentOffload, TransferBOZ, Coarray,
PointerPassObject, MultipleIdenticalDATA,
DefaultStructConstructorNullPointer)
DefaultStructConstructorNullPointer, AssumedRankIoItem)
// Portability and suspicious usage warnings
ENUM_CLASS(UsageWarning, Portability, PointerToUndefinable,

View File

@ -327,10 +327,12 @@ void IoChecker::Enter(const parser::InputItem &spec) {
}
CheckForDefinableVariable(*var, "Input");
if (auto expr{AnalyzeExpr(context_, *var)}) {
auto at{var->GetSource()};
CheckForAssumedRank(UnwrapWholeSymbolDataRef(*expr), at);
CheckForBadIoType(*expr,
flags_.test(Flag::FmtOrNml) ? common::DefinedIo::ReadFormatted
: common::DefinedIo::ReadUnformatted,
var->GetSource());
at);
}
}
@ -651,11 +653,14 @@ void IoChecker::Enter(const parser::OutputItem &item) {
} else if (IsProcedure(*expr)) {
context_.Say(parser::FindSourceLocation(*x),
"Output item must not be a procedure"_err_en_US); // C1233
} else {
auto at{parser::FindSourceLocation(item)};
CheckForAssumedRank(UnwrapWholeSymbolDataRef(*expr), at);
CheckForBadIoType(*expr,
flags_.test(Flag::FmtOrNml) ? common::DefinedIo::WriteFormatted
: common::DefinedIo::WriteUnformatted,
at);
}
CheckForBadIoType(*expr,
flags_.test(Flag::FmtOrNml) ? common::DefinedIo::WriteFormatted
: common::DefinedIo::WriteUnformatted,
parser::FindSourceLocation(item));
}
}
}
@ -1228,6 +1233,17 @@ parser::Message *IoChecker::CheckForBadIoType(const Symbol &symbol,
return nullptr;
}
void IoChecker::CheckForAssumedRank(
const Symbol *symbol, parser::CharBlock namelistLocation) const {
if (symbol && IsAssumedRank(*symbol)) {
evaluate::AttachDeclaration(
context_.Say(namelistLocation,
"Assumed-rank object '%s' may not be an I/O list item"_err_en_US,
symbol->name()),
*symbol);
}
}
void IoChecker::CheckNamelist(const Symbol &namelist, common::DefinedIo which,
parser::CharBlock namelistLocation) const {
if (!context_.HasError(namelist)) {

View File

@ -133,6 +133,7 @@ private:
const SomeExpr &, common::DefinedIo, parser::CharBlock) const;
parser::Message *CheckForBadIoType(
const Symbol &, common::DefinedIo, parser::CharBlock) const;
void CheckForAssumedRank(const Symbol *, parser::CharBlock) const;
void CheckNamelist(
const Symbol &, common::DefinedIo, parser::CharBlock) const;

View File

@ -7228,6 +7228,13 @@ void DeclarationVisitor::FinishNamelists() {
} else if (!ConvertToObjectEntity(symbol->GetUltimate())) {
SayWithDecl(name, *symbol, "'%s' is not a variable"_err_en_US);
context().SetError(*groupSymbol);
} else if (IsAssumedRank(*symbol)) {
evaluate::AttachDeclaration(
context().Warn(common::LanguageFeature::AssumedRankIoItem,
name.source,
"Assumed-rank object '%s' should not be a namelist group item"_port_en_US,
symbol->name()),
*symbol);
}
symbol->GetUltimate().set(Symbol::Flag::InNamelist);
details->add_object(*symbol);

View File

@ -0,0 +1,15 @@
! RUN: %python %S/test_errors.py %s %flang_fc1 -pedantic
subroutine assumedRank(x, y)
real x(..), y(*)
!PORTABILITY: Assumed-rank object 'x' should not be a namelist group item [-Wassumed-rank-io-item]
!ERROR: A namelist group object 'y' must not be assumed-size
namelist /nml/x, y
!ERROR: Assumed-rank object 'x' may not be an I/O list item
!ERROR: Whole assumed-size array 'y' may not appear here without subscripts
read *, x, y
!ERROR: Assumed-rank object 'x' may not be an I/O list item
!ERROR: Whole assumed-size array 'y' may not appear here without subscripts
print *, x, y
read(*,nml=nml)
write(*,nml=nml)
end