[flang] more spec work, handle classic C comments

Original-commit: flang-compiler/f18@d901ee7f50
Reviewed-on: https://github.com/flang-compiler/f18/pull/335
Tree-same-pre-rewrite: false
This commit is contained in:
peter klausler
2019-03-15 13:57:41 -07:00
parent 4b26466375
commit 827407a86a
5 changed files with 102 additions and 35 deletions

View File

@@ -30,7 +30,7 @@ ENUM_CLASS(LanguageFeature, BackslashEscapes, OldDebugLines,
Convert, Dispose, IOListLeadingComma, AbbreviatedEditDescriptor,
ProgramParentheses, PercentRefAndVal, OmitFunctionDummies, CrayPointer,
Hollerith, ArithmeticIF, Assign, AssignedGOTO, Pause, OpenMP,
CruftAfterAmpersand)
CruftAfterAmpersand, ClassicCComments)
using LanguageFeatures =
common::EnumSet<LanguageFeature, LanguageFeature_enumSize>;

View File

@@ -461,11 +461,9 @@ void Preprocessor::Directive(const TokenSequence &dir, Prescanner *prescanner) {
} else if (dirName == "ifdef" || dirName == "ifndef") {
bool doThen{false};
if (nameToken.empty()) {
// Warning, not error, in PGI.
// This misusage appears in WRF & other SPEC codes (might be a local mod).
prescanner->Say(
dir.GetIntervalProvenanceRange(dirOffset, tokens - dirOffset),
"#%s: missing name"_en_US, dirName.data());
"#%s: missing name"_err_en_US, dirName.data());
} else {
j = dir.SkipBlanks(j + 1);
if (j != tokens) {

View File

@@ -96,7 +96,10 @@ void Prescanner::Statement() {
TokenSequence tokens;
LineClassification line{ClassifyLine(lineStart_)};
switch (line.kind) {
case LineClassification::Kind::Comment: NextLine(); return;
case LineClassification::Kind::Comment:
lineStart_ += line.payloadOffset; // advance to '!' or newline
NextLine();
return;
case LineClassification::Kind::IncludeLine:
FortranInclude(lineStart_ + line.payloadOffset);
NextLine();
@@ -283,19 +286,7 @@ void Prescanner::NextChar() {
CHECK(*at_ != '\n');
++at_, ++column_;
if (inPreprocessorDirective_) {
while (*at_ == '/' && at_[1] == '*') {
char star{' '}, slash{' '};
at_ += 2;
column_ += 2;
while ((*at_ != '\n' || slash == '\\') && (star != '*' || slash != '/')) {
star = slash;
slash = *at_++;
++column_;
}
}
while (*at_ == '\\' && at_ + 2 < limit_ && at_[1] == '\n') {
BeginSourceLineAndAdvance();
}
SkipCComments();
} else {
bool rightMarginClip{
inFixedForm_ && column_ > fixedFormColumnLimit_ && !tabInCurrentLine_};
@@ -319,6 +310,28 @@ void Prescanner::NextChar() {
}
}
void Prescanner::SkipCComments() {
while (true) {
if (IsCComment(at_)) {
if (const char *after{SkipCComment(at_)}) {
column_ += after - at_;
// May have skipped over one or more newlines; relocate the start of
// the next line.
lineStart_ = 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_) {
BeginSourceLineAndAdvance();
} else {
break;
}
}
}
void Prescanner::SkipSpaces() {
while (*at_ == ' ' || *at_ == '\t') {
NextChar();
@@ -333,20 +346,60 @@ const char *Prescanner::SkipWhiteSpace(const char *p) {
return p;
}
const char *Prescanner::SkipWhiteSpaceAndCComments(const char *p) const {
while (true) {
if (*p == ' ' || *p == '\t') {
++p;
} else if (IsCComment(p)) {
if (const char *after{SkipCComment(p)}) {
p = after;
} else {
break;
}
} else {
break;
}
}
return p;
}
const char *Prescanner::SkipCComment(const char *p) const {
char star{' '}, slash{' '};
p += 2;
while (star != '*' || slash != '/') {
if (p >= limit_) {
return nullptr; // signifies an unterminated comment
}
star = slash;
slash = *p++;
}
return p;
}
bool Prescanner::NextToken(TokenSequence &tokens) {
CHECK(at_ >= start_ && at_ < limit_);
if (InFixedFormSource()) {
SkipSpaces();
} else if (*at_ == ' ' || *at_ == '\t') {
// Compress white space into a single space character.
// Discard white space at the end of a line.
const auto theSpace{at_};
NextChar();
SkipSpaces();
if (*at_ != '\n') {
tokens.PutNextTokenChar(' ', GetProvenance(theSpace));
tokens.CloseToken();
return true;
} else {
if (*at_ == '/' && IsCComment(at_)) {
// Recognize and skip over classic C style /*comments*/ when
// outside a character literal.
if (features_.ShouldWarn(LanguageFeature::ClassicCComments)) {
Say(GetProvenance(at_), "nonstandard usage: C-style comment"_en_US);
}
SkipCComments();
}
if (*at_ == ' ' || *at_ == '\t') {
// Compress free-form white space into a single space character.
// Discard white space at the end of a line.
const auto theSpace{at_};
NextChar();
SkipSpaces();
if (*at_ != '\n') {
tokens.PutNextTokenChar(' ', GetProvenance(theSpace));
tokens.CloseToken();
return true;
}
}
}
if (insertASpace_) {
@@ -592,9 +645,13 @@ bool Prescanner::IsFixedFormCommentLine(const char *start) const {
return *p == '\n';
}
bool Prescanner::IsFreeFormComment(const char *p) const {
p = SkipWhiteSpace(p);
return *p == '!' || *p == '\n';
const char *Prescanner::IsFreeFormComment(const char *p) const {
p = SkipWhiteSpaceAndCComments(p);
if (*p == '!' || *p == '\n') {
return p;
} else {
return nullptr;
}
}
std::optional<std::size_t> Prescanner::IsIncludeLine(const char *start) const {
@@ -982,8 +1039,9 @@ Prescanner::LineClassification Prescanner::ClassifyLine(
IsFreeFormCompilerDirectiveLine(start)}) {
return std::move(*lc);
}
if (IsFreeFormComment(start)) {
return {LineClassification::Kind::Comment};
if (const char *bang{IsFreeFormComment(start)}) {
return {LineClassification::Kind::Comment,
static_cast<std::size_t>(bang - start)};
}
}
if (std::optional<std::size_t> quoteOffset{IsIncludeLine(start)}) {

View File

@@ -140,11 +140,21 @@ private:
return inFixedForm_ && !inPreprocessorDirective_ && !InCompilerDirective();
}
bool IsCComment(const char *p) const {
return p[0] == '/' && p[1] == '*' &&
(inPreprocessorDirective_ ||
(!inCharLiteral_ &&
features_.IsEnabled(LanguageFeature::ClassicCComments)));
}
void LabelField(TokenSequence &, int outCol = 1);
void SkipToEndOfLine();
void NextChar();
void SkipCComments();
void SkipSpaces();
static const char *SkipWhiteSpace(const char *);
const char *SkipWhiteSpaceAndCComments(const char *) const;
const char *SkipCComment(const char *) const;
bool NextToken(TokenSequence &);
bool ExponentAndKind(TokenSequence &);
void QuotedCharacterLiteral(TokenSequence &);
@@ -152,7 +162,7 @@ private:
bool PadOutCharacterLiteral(TokenSequence &);
bool SkipCommentLine(bool afterAmpersand);
bool IsFixedFormCommentLine(const char *) const;
bool IsFreeFormComment(const char *) const;
const char *IsFreeFormComment(const char *) const;
std::optional<std::size_t> IsIncludeLine(const char *) const;
void FortranInclude(const char *quote);
const char *IsPreprocessorDirectiveLine(const char *) const;

View File

@@ -70,7 +70,8 @@ void CleanUpAtExit() {
}
}
#if _POSIX_C_SOURCE >= 199309L && defined CLOCK_PROCESS_CPUTIME_ID
#if _POSIX_C_SOURCE >= 199309L && _POSIX_TIMERS > 0 && _POSIX_CPUTIME && \
defined CLOCK_PROCESS_CPUTIME_ID
static constexpr bool canTime{true};
double CPUseconds() {
struct timespec tspec;