Skip to content

Commit a5427e7

Browse files
committed
Revert "[flang][runtime] Handle NAN(...) in namelist input (llvm#153101)"
breaks 535.weather at runtime This reverts commit 925db84.
1 parent 19860bb commit a5427e7

File tree

5 files changed

+38
-97
lines changed

5 files changed

+38
-97
lines changed

flang-rt/include/flang-rt/runtime/io-stmt.h

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -432,9 +432,7 @@ template <>
432432
class ListDirectedStatementState<Direction::Input>
433433
: public FormattedIoStatementState<Direction::Input> {
434434
public:
435-
RT_API_ATTRS const NamelistGroup *namelistGroup() const {
436-
return namelistGroup_;
437-
}
435+
RT_API_ATTRS bool inNamelistSequence() const { return inNamelistSequence_; }
438436
RT_API_ATTRS int EndIoStatement();
439437

440438
// Skips value separators, handles repetition and null values.
@@ -447,19 +445,18 @@ class ListDirectedStatementState<Direction::Input>
447445
// input statement. This member function resets some state so that
448446
// repetition and null values work correctly for each successive
449447
// NAMELIST input item.
450-
RT_API_ATTRS void ResetForNextNamelistItem(
451-
const NamelistGroup *namelistGroup) {
448+
RT_API_ATTRS void ResetForNextNamelistItem(bool inNamelistSequence) {
452449
remaining_ = 0;
453450
if (repeatPosition_) {
454451
repeatPosition_->Cancel();
455452
}
456453
eatComma_ = false;
457454
realPart_ = imaginaryPart_ = false;
458-
namelistGroup_ = namelistGroup;
455+
inNamelistSequence_ = inNamelistSequence;
459456
}
460457

461458
protected:
462-
const NamelistGroup *namelistGroup_{nullptr};
459+
bool inNamelistSequence_{false};
463460

464461
private:
465462
int remaining_{0}; // for "r*" repetition

flang-rt/lib/runtime/edit-input.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -534,7 +534,7 @@ static RT_API_ATTRS ScannedRealInput ScanRealInput(
534534
next = io.NextInField(remaining, edit);
535535
}
536536
if (!next || *next == ')') { // NextInField fails on separators like ')'
537-
std::size_t byteCount{1};
537+
std::size_t byteCount{0};
538538
if (!next) {
539539
next = io.GetCurrentChar(byteCount);
540540
}

flang-rt/lib/runtime/io-stmt.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1097,7 +1097,7 @@ ChildListIoStatementState<DIR>::ChildListIoStatementState(
10971097
if constexpr (DIR == Direction::Input) {
10981098
if (auto *listInput{child.parent()
10991099
.get_if<ListDirectedStatementState<Direction::Input>>()}) {
1100-
this->namelistGroup_ = listInput->namelistGroup();
1100+
this->inNamelistSequence_ = listInput->inNamelistSequence();
11011101
}
11021102
}
11031103
#else

flang-rt/lib/runtime/namelist.cpp

Lines changed: 32 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,8 @@ bool IODEF(OutputNamelist)(Cookie cookie, const NamelistGroup &group) {
4444
if ((connection.NeedAdvance(prefixLen) &&
4545
!(io.AdvanceRecord() && EmitAscii(io, " ", 1))) ||
4646
!EmitAscii(io, prefix, prefixLen) ||
47-
(connection.NeedAdvance(runtime::strlen(str) + (suffix != ' ')) &&
47+
(connection.NeedAdvance(
48+
Fortran::runtime::strlen(str) + (suffix != ' ')) &&
4849
!(io.AdvanceRecord() && EmitAscii(io, " ", 1)))) {
4950
return false;
5051
}
@@ -101,8 +102,8 @@ static constexpr RT_API_ATTRS char NormalizeIdChar(char32_t ch) {
101102
return static_cast<char>(ch >= 'A' && ch <= 'Z' ? ch - 'A' + 'a' : ch);
102103
}
103104

104-
static RT_API_ATTRS bool GetLowerCaseName(IoStatementState &io, char buffer[],
105-
std::size_t maxLength, bool crashIfTooLong = true) {
105+
static RT_API_ATTRS bool GetLowerCaseName(
106+
IoStatementState &io, char buffer[], std::size_t maxLength) {
106107
std::size_t byteLength{0};
107108
if (auto ch{io.GetNextNonBlank(byteLength)}) {
108109
if (IsLegalIdStart(*ch)) {
@@ -116,10 +117,8 @@ static RT_API_ATTRS bool GetLowerCaseName(IoStatementState &io, char buffer[],
116117
if (j <= maxLength) {
117118
return true;
118119
}
119-
if (crashIfTooLong) {
120-
io.GetIoErrorHandler().SignalError(
121-
"Identifier '%s...' in NAMELIST input group is too long", buffer);
122-
}
120+
io.GetIoErrorHandler().SignalError(
121+
"Identifier '%s...' in NAMELIST input group is too long", buffer);
123122
}
124123
}
125124
return false;
@@ -357,8 +356,9 @@ static RT_API_ATTRS bool HandleComponent(IoStatementState &io, Descriptor &desc,
357356
const DescriptorAddendum *addendum{source.Addendum()};
358357
if (const typeInfo::DerivedType *
359358
type{addendum ? addendum->derivedType() : nullptr}) {
360-
if (const typeInfo::Component *comp{
361-
type->FindDataComponent(compName, runtime::strlen(compName))}) {
359+
if (const typeInfo::Component *
360+
comp{type->FindDataComponent(
361+
compName, Fortran::runtime::strlen(compName))}) {
362362
bool createdDesc{false};
363363
if (comp->rank() > 0 && source.rank() > 0) {
364364
// If base and component are both arrays, the component name
@@ -483,7 +483,7 @@ bool IODEF(InputNamelist)(Cookie cookie, const NamelistGroup &group) {
483483
handler.SignalError("NAMELIST input group has no name");
484484
return false;
485485
}
486-
if (runtime::strcmp(group.groupName, name) == 0) {
486+
if (Fortran::runtime::strcmp(group.groupName, name) == 0) {
487487
break; // found it
488488
}
489489
SkipNamelistGroup(io);
@@ -502,7 +502,7 @@ bool IODEF(InputNamelist)(Cookie cookie, const NamelistGroup &group) {
502502
}
503503
std::size_t itemIndex{0};
504504
for (; itemIndex < group.items; ++itemIndex) {
505-
if (runtime::strcmp(name, group.item[itemIndex].name) == 0) {
505+
if (Fortran::runtime::strcmp(name, group.item[itemIndex].name) == 0) {
506506
break;
507507
}
508508
}
@@ -576,14 +576,13 @@ bool IODEF(InputNamelist)(Cookie cookie, const NamelistGroup &group) {
576576
if (const auto *addendum{useDescriptor->Addendum()};
577577
addendum && addendum->derivedType()) {
578578
const NonTbpDefinedIoTable *table{group.nonTbpDefinedIo};
579-
listInput->ResetForNextNamelistItem(&group);
579+
listInput->ResetForNextNamelistItem(/*inNamelistSequence=*/true);
580580
if (!IONAME(InputDerivedType)(cookie, *useDescriptor, table) &&
581581
handler.InError()) {
582582
return false;
583583
}
584584
} else {
585-
listInput->ResetForNextNamelistItem(
586-
useDescriptor->rank() > 0 ? &group : nullptr);
585+
listInput->ResetForNextNamelistItem(useDescriptor->rank() > 0);
587586
if (!descr::DescriptorIO<Direction::Input>(io, *useDescriptor) &&
588587
handler.InError()) {
589588
return false;
@@ -607,51 +606,27 @@ bool IODEF(InputNamelist)(Cookie cookie, const NamelistGroup &group) {
607606
}
608607

609608
RT_API_ATTRS bool IsNamelistNameOrSlash(IoStatementState &io) {
610-
auto *listInput{io.get_if<ListDirectedStatementState<Direction::Input>>()};
611-
if (!listInput || !listInput->namelistGroup()) {
612-
return false; // not namelist
613-
}
614-
SavedPosition savedPosition{io};
615-
std::size_t byteCount{0};
616-
auto ch{io.GetNextNonBlank(byteCount)};
617-
if (!ch) {
618-
return false;
619-
} else if (!IsLegalIdStart(*ch)) {
620-
return *ch == '/' || *ch == '&' || *ch == '$';
621-
}
622-
char id[nameBufferSize];
623-
if (!GetLowerCaseName(io, id, sizeof id, /*crashIfTooLong=*/false)) {
624-
return true; // long name
625-
}
626-
// It looks like a name, but might be "inf" or "nan". Check what
627-
// follows.
628-
ch = io.GetNextNonBlank(byteCount);
629-
if (!ch) {
630-
return false;
631-
} else if (*ch == '=' || *ch == '%') {
632-
return true;
633-
} else if (*ch != '(') {
634-
return false;
635-
} else if (runtime::strcmp(id, "nan") != 0) {
636-
return true;
637-
}
638-
// "nan(" ambiguity
639-
int depth{1};
640-
while (true) {
641-
io.HandleRelativePosition(byteCount);
642-
ch = io.GetNextNonBlank(byteCount);
643-
if (depth == 0) {
644-
// nan(...) followed by '=', '%', or '('?
645-
break;
646-
} else if (!ch) {
647-
return true; // not a valid NaN(...)
648-
} else if (*ch == '(') {
649-
++depth;
650-
} else if (*ch == ')') {
651-
--depth;
609+
if (auto *listInput{
610+
io.get_if<ListDirectedStatementState<Direction::Input>>()}) {
611+
if (listInput->inNamelistSequence()) {
612+
SavedPosition savedPosition{io};
613+
std::size_t byteCount{0};
614+
if (auto ch{io.GetNextNonBlank(byteCount)}) {
615+
if (IsLegalIdStart(*ch)) {
616+
do {
617+
io.HandleRelativePosition(byteCount);
618+
ch = io.GetCurrentChar(byteCount);
619+
} while (ch && IsLegalIdChar(*ch));
620+
ch = io.GetNextNonBlank(byteCount);
621+
// TODO: how to deal with NaN(...) ambiguity?
622+
return ch && (*ch == '=' || *ch == '(' || *ch == '%');
623+
} else {
624+
return *ch == '/' || *ch == '&' || *ch == '$';
625+
}
626+
}
652627
}
653628
}
654-
return ch && (*ch == '=' || *ch == '%' || *ch == '(');
629+
return false;
655630
}
656631

657632
RT_OFFLOAD_API_GROUP_END

flang-rt/unittests/Runtime/Namelist.cpp

Lines changed: 0 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -334,35 +334,4 @@ TEST(NamelistTests, RealValueForInt) {
334334
EXPECT_EQ(got, expect);
335335
}
336336

337-
TEST(NamelistTests, NanInputAmbiguity) {
338-
OwningPtr<Descriptor> xDesc{// real :: x(5) = 0.
339-
MakeArray<TypeCategory::Real, static_cast<int>(sizeof(float))>(
340-
std::vector<int>{5}, std::vector<float>{{0, 0, 0, 0, 0}})};
341-
OwningPtr<Descriptor> nanDesc{// real :: nan(2) = 0.
342-
MakeArray<TypeCategory::Real, static_cast<int>(sizeof(float))>(
343-
std::vector<int>{2}, std::vector<float>{{0, 0}})};
344-
const NamelistGroup::Item items[]{{"x", *xDesc}, {"nan", *nanDesc}};
345-
const NamelistGroup group{"nml", 2, items};
346-
static char t1[]{"&nml x=1 2 nan(q) 4 nan(1)=5 nan(q)/"};
347-
StaticDescriptor<1, true> statDesc;
348-
Descriptor &internalDesc{statDesc.descriptor()};
349-
internalDesc.Establish(TypeCode{CFI_type_char},
350-
/*elementBytes=*/std::strlen(t1), t1, 0, nullptr, CFI_attribute_pointer);
351-
auto inCookie{IONAME(BeginInternalArrayListInput)(
352-
internalDesc, nullptr, 0, __FILE__, __LINE__)};
353-
ASSERT_TRUE(IONAME(InputNamelist)(inCookie, group));
354-
ASSERT_EQ(IONAME(EndIoStatement)(inCookie), IostatOk)
355-
<< "namelist real input for nans";
356-
char out[40];
357-
internalDesc.Establish(TypeCode{CFI_type_char}, /*elementBytes=*/sizeof out,
358-
out, 0, nullptr, CFI_attribute_pointer);
359-
auto outCookie{IONAME(BeginInternalArrayListOutput)(
360-
internalDesc, nullptr, 0, __FILE__, __LINE__)};
361-
ASSERT_TRUE(IONAME(OutputNamelist)(outCookie, group));
362-
ASSERT_EQ(IONAME(EndIoStatement)(outCookie), IostatOk) << "namelist output";
363-
std::string got{out, sizeof out};
364-
static const std::string expect{" &NML X= 1. 2. NaN 4. 0.,NAN= 5. NaN/ "};
365-
EXPECT_EQ(got, expect);
366-
}
367-
368337
// TODO: Internal NAMELIST error tests

0 commit comments

Comments
 (0)