[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:
@@ -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>;
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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)}) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user