[flang] Accept source files with no program units (flang-compiler/f18#658)

update documentation

Original-commit: flang-compiler/f18@3dfb831499
Reviewed-on: https://github.com/flang-compiler/f18/pull/859
This commit is contained in:
peter klausler 2019-12-06 09:37:07 -08:00
parent 47575727f7
commit 6c390a780b
7 changed files with 25 additions and 23 deletions

View File

@ -109,8 +109,10 @@ Extensions, deletions, and legacy features supported by default
* When a dummy argument is `POINTER` or `ALLOCATABLE` and is `INTENT(IN)`, we
relax enforcement of some requirements on actual arguments that must otherwise
hold true for definable arguments.
* Assignment of `LOGICAL` to `INTEGER` and vice versa (but not other types).
The values are normalized.
* Assignment of `LOGICAL` to `INTEGER` and vice versa (but not other types) is
allowed. The values are normalized.
* An effectively empty source file (no program unit) is accepted and
produces an empty relocatable output file.
Extensions supported when enabled by options
--------------------------------------------

View File

@ -33,7 +33,8 @@ ENUM_CLASS(LanguageFeature, BackslashEscapes, OldDebugLines,
Hollerith, ArithmeticIF, Assign, AssignedGOTO, Pause, OpenMP,
CruftAfterAmpersand, ClassicCComments, AdditionalFormats, BigIntLiterals,
RealDoControls, EquivalenceNumericWithCharacter, AdditionalIntrinsics,
AnonymousParents, OldLabelDoEndStatements, LogicalIntegerAssignment)
AnonymousParents, OldLabelDoEndStatements, LogicalIntegerAssignment,
EmptySourceFile)
using LanguageFeatures = EnumSet<LanguageFeature, LanguageFeature_enumSize>;

View File

@ -276,10 +276,12 @@ constexpr auto scalarIntConstantExpr{scalar(intConstantExpr)};
// Consequently, a program unit END statement should be the last statement
// on its line. We parse those END statements via unterminatedStatement()
// and then skip over the end of the line here.
TYPE_PARSER(construct<Program>(some(StartNewSubprogram{} >>
Parser<ProgramUnit>{} / skipMany(";"_tok) / space /
recovery(endOfLine, SkipPast<'\n'>{}))) /
skipStuffBeforeStatement)
TYPE_PARSER(construct<Program>(
extension<LanguageFeature::EmptySourceFile>(skipStuffBeforeStatement >>
!nextCh >> defaulted(cut >> some(Parser<ProgramUnit>{}))) ||
some(StartNewSubprogram{} >> Parser<ProgramUnit>{} / skipMany(";"_tok) /
space / recovery(endOfLine, SkipPast<'\n'>{})) /
skipStuffBeforeStatement))
// R502 program-unit ->
// main-program | external-subprogram | module | submodule | block-data

View File

@ -50,11 +50,6 @@ const SourceFile *Parsing::Prescan(const std::string &path, Options options) {
return sourceFile;
}
CHECK(sourceFile);
if (sourceFile->bytes() == 0) {
ProvenanceRange range{allSources.AddCompilerInsertion(path)};
messages_.Say(range, "file is empty"_err_en_US);
return sourceFile;
}
if (!options.isModuleFile) {
// For .mod files we always want to look in the search directories.
@ -86,6 +81,11 @@ const SourceFile *Parsing::Prescan(const std::string &path, Options options) {
ProvenanceRange range{allSources.AddIncludedFile(
*sourceFile, ProvenanceRange{}, options.isModuleFile)};
prescanner.Prescan(range);
if (cooked_.BufferedBytes() == 0 && !options.isModuleFile) {
// Input is empty. Append a newline so that any warning
// message about nonstandard usage will have provenance.
cooked_.Put('\n', range.start());
}
cooked_.Marshal();
if (options.needProvenanceRangeToCharBlockMappings) {
cooked_.CompileProvenanceRangeToOffsetMappings();

View File

@ -461,6 +461,8 @@ std::optional<CharBlock> CookedSource::GetCharBlock(
}
}
std::size_t CookedSource::BufferedBytes() const { return buffer_.bytes(); }
void CookedSource::Marshal() {
CHECK(provenanceMap_.SizeInBytes() == buffer_.bytes());
provenanceMap_.Put(allSources_.AddCompilerInsertion("(after end of source)"));

View File

@ -262,6 +262,7 @@ public:
provenanceMap_.Put(pm);
}
std::size_t BufferedBytes() const;
void Marshal(); // marshals text into one contiguous block
void CompileProvenanceRangeToOffsetMappings();
std::string AcquireData() { return std::move(data_); }

View File

@ -223,17 +223,11 @@ bool SourceFile::ReadFile(std::string errorPath, std::stringstream *error) {
--openFileDescriptors;
}
fileDescriptor_ = -1;
if (buffer.bytes() == 0) {
// empty file
address_ = content_ = nullptr;
size_ = bytes_ = 0;
} else {
normalized_ = buffer.MarshalNormalized();
address_ = normalized_.data();
size_ = normalized_.size();
IdentifyPayload();
RecordLineStarts();
}
normalized_ = buffer.MarshalNormalized();
address_ = normalized_.c_str();
size_ = normalized_.size();
IdentifyPayload();
RecordLineStarts();
return true;
}