forked from OSchip/llvm-project
[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:
parent
47575727f7
commit
6c390a780b
|
@ -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
|
||||
--------------------------------------------
|
||||
|
|
|
@ -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>;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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)"));
|
||||
|
|
|
@ -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_); }
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue