[flang] Fix bug flang-compiler/f18#491 (and replace a misleading name)

Original-commit: flang-compiler/f18@d0d154e312
Reviewed-on: https://github.com/flang-compiler/f18/pull/492
Tree-same-pre-rewrite: false
This commit is contained in:
peter klausler 2019-06-11 12:06:18 -07:00
parent 83cf7caa56
commit a306d92675
2 changed files with 69 additions and 58 deletions

View File

@ -69,14 +69,14 @@ void Prescanner::Prescan(ProvenanceRange range) {
CHECK(source != nullptr);
start_ = source->content() + offset;
limit_ = start_ + range.size();
lineStart_ = start_;
nextLine_ = start_;
const bool beganInFixedForm{inFixedForm_};
if (prescannerNesting_ > maxPrescannerNesting) {
Say(GetProvenance(start_),
"too many nested INCLUDE/#include files, possibly circular"_err_en_US);
return;
}
while (lineStart_ < limit_) {
while (nextLine_ < limit_) {
Statement();
}
if (inFixedForm_ != beganInFixedForm) {
@ -94,14 +94,14 @@ void Prescanner::Prescan(ProvenanceRange range) {
void Prescanner::Statement() {
TokenSequence tokens;
LineClassification line{ClassifyLine(lineStart_)};
LineClassification line{ClassifyLine(nextLine_)};
switch (line.kind) {
case LineClassification::Kind::Comment:
lineStart_ += line.payloadOffset; // advance to '!' or newline
nextLine_ += line.payloadOffset; // advance to '!' or newline
NextLine();
return;
case LineClassification::Kind::IncludeLine:
FortranInclude(lineStart_ + line.payloadOffset);
FortranInclude(nextLine_ + line.payloadOffset);
NextLine();
return;
case LineClassification::Kind::ConditionalCompilationDirective:
@ -224,7 +224,7 @@ void Prescanner::Statement() {
}
TokenSequence Prescanner::TokenizePreprocessorDirective() {
CHECK(lineStart_ < limit_ && !inPreprocessorDirective_);
CHECK(nextLine_ < limit_ && !inPreprocessorDirective_);
auto saveAt{at_};
inPreprocessorDirective_ = true;
BeginSourceLineAndAdvance();
@ -237,13 +237,13 @@ TokenSequence Prescanner::TokenizePreprocessorDirective() {
}
void Prescanner::NextLine() {
void *vstart{static_cast<void *>(const_cast<char *>(lineStart_))};
void *v{std::memchr(vstart, '\n', limit_ - lineStart_)};
void *vstart{static_cast<void *>(const_cast<char *>(nextLine_))};
void *v{std::memchr(vstart, '\n', limit_ - nextLine_)};
if (v == nullptr) {
lineStart_ = limit_;
nextLine_ = limit_;
} else {
const char *nl{const_cast<const char *>(static_cast<char *>(v))};
lineStart_ = nl + 1;
nextLine_ = nl + 1;
}
}
@ -282,26 +282,38 @@ void Prescanner::SkipToEndOfLine() {
}
}
bool Prescanner::MustSkipToEndOfLine() const {
if (inFixedForm_ && column_ > fixedFormColumnLimit_ && !tabInCurrentLine_) {
return true; // skip over ignored columns in right margin (73:80)
} else if (*at_ == '!' && !inCharLiteral_) {
return true; // inline comment goes to end of source line
} else {
return false;
}
}
void Prescanner::NextChar() {
CHECK(*at_ != '\n');
++at_, ++column_;
if (inPreprocessorDirective_) {
SkipCComments();
} else {
bool rightMarginClip{
inFixedForm_ && column_ > fixedFormColumnLimit_ && !tabInCurrentLine_};
bool skipping{rightMarginClip || (*at_ == '!' && !inCharLiteral_)};
if (skipping) {
bool mightNeedSpace{false};
if (MustSkipToEndOfLine()) {
SkipToEndOfLine();
} else {
mightNeedSpace = *at_ == '\n';
}
while (*at_ == '\n' || *at_ == '&') {
bool mightNeedSpace{*at_ == '\n' && !skipping};
if (inFixedForm_) {
if (!FixedFormContinuation(mightNeedSpace)) {
return;
bool continued{inFixedForm_ ? FixedFormContinuation(mightNeedSpace)
: FreeFormContinuation()};
if (continued) {
if (MustSkipToEndOfLine()) {
SkipToEndOfLine();
}
} else if (!FreeFormContinuation()) {
return;
mightNeedSpace = false;
} else {
break;
}
}
if (*at_ == '\t') {
@ -317,14 +329,14 @@ void Prescanner::SkipCComments() {
column_ += after - at_;
// May have skipped over one or more newlines; relocate the start of
// the next line.
lineStart_ = at_ = after;
nextLine_ = at_ = after;
NextLine();
} else {
Say(GetProvenance(at_), "unclosed C-style comment"_err_en_US);
break;
}
} else if (inPreprocessorDirective_ && at_[0] == '\\' && at_ + 2 < limit_ &&
at_[1] == '\n' && lineStart_ < limit_) {
at_[1] == '\n' && nextLine_ < limit_) {
BeginSourceLineAndAdvance();
} else {
break;
@ -636,21 +648,19 @@ bool Prescanner::PadOutCharacterLiteral(TokenSequence &tokens) {
bool Prescanner::IsFixedFormCommentLine(const char *start) const {
const char *p{start};
char ch{*p};
if (IsFixedFormCommentChar(ch) || ch == '%' || // VAX %list, %eject, &c.
((ch == 'D' || ch == 'd') &&
if (IsFixedFormCommentChar(*p) || *p == '%' || // VAX %list, %eject, &c.
((*p == 'D' || *p == 'd') &&
!features_.IsEnabled(LanguageFeature::OldDebugLines))) {
return true;
}
bool anyTabs{false};
while (true) {
ch = *p;
if (ch == ' ') {
if (*p == ' ') {
++p;
} else if (ch == '\t') {
} else if (*p == '\t') {
anyTabs = true;
++p;
} else if (ch == '0' && !anyTabs && p == start + 5) {
} else if (*p == '0' && !anyTabs && p == start + 5) {
++p; // 0 in column 6 must treated as a space
} else {
break;
@ -718,7 +728,7 @@ void Prescanner::FortranInclude(const char *firstQuote) {
"excess characters after path name"_en_US);
}
std::stringstream error;
Provenance provenance{GetProvenance(lineStart_)};
Provenance provenance{GetProvenance(nextLine_)};
AllSources &allSources{cooked_.allSources()};
const SourceFile *currentFile{allSources.GetSourceFile(provenance)};
if (currentFile != nullptr) {
@ -732,7 +742,7 @@ void Prescanner::FortranInclude(const char *firstQuote) {
Say(provenance, "INCLUDE: %s"_err_en_US, error.str());
} else if (included->bytes() > 0) {
ProvenanceRange includeLineRange{
provenance, static_cast<std::size_t>(p - lineStart_)};
provenance, static_cast<std::size_t>(p - nextLine_)};
ProvenanceRange fileRange{
allSources.AddIncludedFile(*included, includeLineRange)};
Prescanner{*this}.Prescan(fileRange);
@ -757,11 +767,11 @@ const char *Prescanner::IsPreprocessorDirectiveLine(const char *start) const {
}
bool Prescanner::IsNextLinePreprocessorDirective() const {
return IsPreprocessorDirectiveLine(lineStart_) != nullptr;
return IsPreprocessorDirectiveLine(nextLine_) != nullptr;
}
bool Prescanner::SkipCommentLine(bool afterAmpersand) {
if (lineStart_ >= limit_) {
if (nextLine_ >= limit_) {
if (afterAmpersand && prescannerNesting_ > 0) {
// A continuation marker at the end of the last line in an
// include file inhibits the newline for that line.
@ -770,7 +780,7 @@ bool Prescanner::SkipCommentLine(bool afterAmpersand) {
}
return false;
}
auto lineClass{ClassifyLine(lineStart_)};
auto lineClass{ClassifyLine(nextLine_)};
if (lineClass.kind == LineClassification::Kind::Comment) {
NextLine();
return true;
@ -795,11 +805,11 @@ bool Prescanner::SkipCommentLine(bool afterAmpersand) {
}
const char *Prescanner::FixedFormContinuationLine(bool mightNeedSpace) {
if (lineStart_ >= limit_) {
if (nextLine_ >= limit_) {
return nullptr;
}
tabInCurrentLine_ = false;
char col1{*lineStart_};
char col1{*nextLine_};
if (InCompilerDirective()) {
// Must be a continued compiler directive.
if (!IsFixedFormCommentChar(col1)) {
@ -811,21 +821,21 @@ const char *Prescanner::FixedFormContinuationLine(bool mightNeedSpace) {
if (ch == '\0') {
break;
}
if (ch != ToLowerCaseLetter(lineStart_[j])) {
if (ch != ToLowerCaseLetter(nextLine_[j])) {
return nullptr;
}
}
for (; j < 5; ++j) {
if (lineStart_[j] != ' ') {
if (nextLine_[j] != ' ') {
return nullptr;
}
}
char col6{lineStart_[5]};
char col6{nextLine_[5]};
if (col6 != '\n' && col6 != '\t' && col6 != ' ' && col6 != '0') {
if (lineStart_[6] != ' ' && mightNeedSpace) {
if (nextLine_[6] != ' ' && mightNeedSpace) {
insertASpace_ = true;
}
return lineStart_ + 6;
return nextLine_ + 6;
}
return nullptr;
} else {
@ -836,24 +846,24 @@ const char *Prescanner::FixedFormContinuationLine(bool mightNeedSpace) {
// Extension: '&' as continuation marker
if (features_.ShouldWarn(
LanguageFeature::FixedFormContinuationWithColumn1Ampersand)) {
Say(GetProvenance(lineStart_), "nonstandard usage"_en_US);
Say(GetProvenance(nextLine_), "nonstandard usage"_en_US);
}
return lineStart_ + 1;
return nextLine_ + 1;
}
if (col1 == '\t' && lineStart_[1] >= '1' && lineStart_[1] <= '9') {
if (col1 == '\t' && nextLine_[1] >= '1' && nextLine_[1] <= '9') {
tabInCurrentLine_ = true;
return lineStart_ + 2; // VAX extension
return nextLine_ + 2; // VAX extension
}
if (col1 == ' ' && lineStart_[1] == ' ' && lineStart_[2] == ' ' &&
lineStart_[3] == ' ' && lineStart_[4] == ' ') {
char col6{lineStart_[5]};
if (col1 == ' ' && nextLine_[1] == ' ' && nextLine_[2] == ' ' &&
nextLine_[3] == ' ' && nextLine_[4] == ' ') {
char col6{nextLine_[5]};
if (col6 != '\n' && col6 != '\t' && col6 != ' ' && col6 != '0') {
return lineStart_ + 6;
return nextLine_ + 6;
}
}
if (delimiterNesting_ > 0) {
if (!IsFixedFormCommentChar(col1)) {
return lineStart_;
return nextLine_;
}
}
}
@ -861,7 +871,7 @@ const char *Prescanner::FixedFormContinuationLine(bool mightNeedSpace) {
}
const char *Prescanner::FreeFormContinuationLine(bool ampersand) {
const char *p{lineStart_};
const char *p{nextLine_};
if (p >= limit_) {
return nullptr;
}
@ -892,7 +902,7 @@ const char *Prescanner::FreeFormContinuationLine(bool ampersand) {
} else if (*p == '!' || *p == '\n' || *p == '#') {
return nullptr;
} else if (ampersand || delimiterNesting_ > 0) {
if (p > lineStart_) {
if (p > nextLine_) {
--p;
} else {
insertASpace_ = true;
@ -917,7 +927,7 @@ bool Prescanner::FixedFormContinuation(bool mightNeedSpace) {
NextLine();
return true;
}
} while (SkipCommentLine(false));
} while (SkipCommentLine(false /* not after & */));
return false;
}

View File

@ -65,7 +65,7 @@ public:
void NextLine();
// Callbacks for use by Preprocessor.
bool IsAtEnd() const { return lineStart_ >= limit_; }
bool IsAtEnd() const { return nextLine_ >= limit_; }
bool IsNextLinePreprocessorDirective() const;
TokenSequence TokenizePreprocessorDirective();
Provenance GetCurrentProvenance() const { return GetProvenance(at_); }
@ -106,7 +106,7 @@ private:
}
void BeginSourceLineAndAdvance() {
BeginSourceLine(lineStart_);
BeginSourceLine(nextLine_);
NextLine();
}
@ -149,6 +149,7 @@ private:
void LabelField(TokenSequence &, int outCol = 1);
void SkipToEndOfLine();
bool MustSkipToEndOfLine() const;
void NextChar();
void SkipCComments();
void SkipSpaces();
@ -191,12 +192,12 @@ private:
Provenance startProvenance_;
const char *start_{nullptr}; // beginning of current source file content
const char *limit_{nullptr}; // first address after end of current source
const char *lineStart_{nullptr}; // next line to process; <= limit_
const char *nextLine_{nullptr}; // next line to process; <= limit_
const char *directiveSentinel_{nullptr}; // current compiler directive
// This data members are state for processing the source line containing
// "at_", which goes to up to the newline character before "lineStart_".
const char *at_{nullptr}; // next character to process; < lineStart_
// "at_", which goes to up to the newline character before "nextLine_".
const char *at_{nullptr}; // next character to process; < nextLine_
int column_{1}; // card image column position of next character
bool tabInCurrentLine_{false};
bool slashInCurrentLine_{false};