Skip to content

Commit 8df63a2

Browse files
committed
[flang] Support the color diagnostics on scanning, parsing, and semantics
The options -f{no-}color-diagnostics have been supported in driver. This supports the behaviors in scanning, parsing, and semantics, and the behaviors are exactly the same as the driver. To illustrate the added behaviour, consider the following input file: ```! file.f90 program m integer :: i = k end ``` In the following invocations, "error: Must be a constant value" _will be_ formatted: ``` $ flang-new file.f90 error: Semantic errors in file.f90 ./file.f90:2:18: error: Must be a constant value integer :: i = k ``` Note that "error: Semantic errors in file.f90" is also formatted, which is supported in https://reviews.llvm.org/D126164. Also note that only "error", "warning" and "portability" are formatted. Check the following input file: ```! file2.f90 program m integer :: i = end ``` ``` $ flang-new test2.f90 error: Could not parse test2.f90 ./test2.f90:2:11: error: expected '(' integer :: i = ^ ./test2.f90:2:3: in the context: statement function definition integer :: i = ^ ... ``` The "error: Could not parse test2.f90" and "error: expected '('" are formatted. Others such as "in the context" are not formatted yet, which may or may not be supported. Reviewed By: awarzynski Differential Revision: https://reviews.llvm.org/D126166
1 parent 02761e3 commit 8df63a2

File tree

12 files changed

+126
-18
lines changed

12 files changed

+126
-18
lines changed

flang/docs/ReleaseNotes.md

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,7 @@ page](https://llvm.org/releases/).
4141
In particular, both `-fcolor-diagnostics` and `-fno-color-diagnostics` are
4242
now available in `flang-new` (the diagnostics are formatted by default). In
4343
the frontend driver, `flang-new -fc1`, only `-fcolor-diagnostics` is
44-
available (by default, the diagnostics are not formatted). Note that this
45-
will only affect the diagnostics printed by driver (scanning, parsing and
46-
semantic diagnostics are not affected).
44+
available (by default, the diagnostics are not formatted).
4745

4846
## Windows Support
4947

flang/include/flang/Parser/parsing.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ struct Options {
3939
bool needProvenanceRangeToCharBlockMappings{false};
4040
Fortran::parser::Encoding encoding{Fortran::parser::Encoding::UTF_8};
4141
bool prescanAndReformat{false}; // -E
42+
bool showColors{false};
4243
};
4344

4445
class Parsing {
@@ -65,9 +66,12 @@ class Parsing {
6566
void ClearLog();
6667

6768
void EmitMessage(llvm::raw_ostream &o, const char *at,
68-
const std::string &message, bool echoSourceLine = false) const {
69+
const std::string &message, const std::string &prefix,
70+
llvm::raw_ostream::Colors color = llvm::raw_ostream::SAVEDCOLOR,
71+
bool echoSourceLine = false) const {
6972
allCooked_.allSources().EmitMessage(o,
70-
allCooked_.GetProvenanceRange(CharBlock(at)), message, echoSourceLine);
73+
allCooked_.GetProvenanceRange(CharBlock(at)), message, prefix, color,
74+
echoSourceLine);
7175
}
7276

7377
private:

flang/include/flang/Parser/provenance.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,8 +165,11 @@ class AllSources {
165165
bool IsValid(ProvenanceRange range) const {
166166
return range.size() > 0 && range_.Contains(range);
167167
}
168+
void setShowColors(bool showColors) { showColors_ = showColors; }
169+
bool getShowColors() const { return showColors_; }
168170
void EmitMessage(llvm::raw_ostream &, const std::optional<ProvenanceRange> &,
169-
const std::string &message, bool echoSourceLine = false) const;
171+
const std::string &message, const std::string &prefix,
172+
llvm::raw_ostream::Colors color, bool echoSourceLine = false) const;
170173
const SourceFile *GetSourceFile(
171174
Provenance, std::size_t *offset = nullptr) const;
172175
const char *GetSource(ProvenanceRange) const;
@@ -214,6 +217,7 @@ class AllSources {
214217
std::vector<std::unique_ptr<SourceFile>> ownedSourceFiles_;
215218
std::list<std::string> searchPath_;
216219
Encoding encoding_{Encoding::UTF_8};
220+
bool showColors_{false};
217221
};
218222

219223
// Represents the result of preprocessing and prescanning a single source

flang/lib/Frontend/CompilerInvocation.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -769,6 +769,9 @@ void CompilerInvocation::setFortranOpts() {
769769
if (frontendOptions.instrumentedParse)
770770
fortranOptions.instrumentedParse = true;
771771

772+
if (frontendOptions.showColors)
773+
fortranOptions.showColors = true;
774+
772775
if (frontendOptions.needProvenanceRangeToCharBlockMappings)
773776
fortranOptions.needProvenanceRangeToCharBlockMappings = true;
774777

flang/lib/Parser/message.cpp

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -234,18 +234,33 @@ static std::string Prefix(Severity severity) {
234234
return "";
235235
}
236236

237+
static llvm::raw_ostream::Colors PrefixColor(Severity severity) {
238+
switch (severity) {
239+
case Severity::Error:
240+
case Severity::Todo:
241+
return llvm::raw_ostream::RED;
242+
case Severity::Warning:
243+
case Severity::Portability:
244+
return llvm::raw_ostream::MAGENTA;
245+
default:
246+
// TODO: Set the color.
247+
break;
248+
}
249+
return llvm::raw_ostream::SAVEDCOLOR;
250+
}
251+
237252
void Message::Emit(llvm::raw_ostream &o, const AllCookedSources &allCooked,
238253
bool echoSourceLine) const {
239254
std::optional<ProvenanceRange> provenanceRange{GetProvenanceRange(allCooked)};
240255
const AllSources &sources{allCooked.allSources()};
241-
sources.EmitMessage(
242-
o, provenanceRange, Prefix(severity()) + ToString(), echoSourceLine);
256+
sources.EmitMessage(o, provenanceRange, ToString(), Prefix(severity()),
257+
PrefixColor(severity()), echoSourceLine);
243258
bool isContext{attachmentIsContext_};
244259
for (const Message *attachment{attachment_.get()}; attachment;
245260
attachment = attachment->attachment_.get()) {
261+
Severity severity = isContext ? Severity::Context : attachment->severity();
246262
sources.EmitMessage(o, attachment->GetProvenanceRange(allCooked),
247-
Prefix(isContext ? Severity::Context : attachment->severity()) +
248-
attachment->ToString(),
263+
attachment->ToString(), Prefix(severity), PrefixColor(severity),
249264
echoSourceLine);
250265
}
251266
}

flang/lib/Parser/parsing.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,9 @@ const SourceFile *Parsing::Prescan(const std::string &path, Options options) {
9696
if (options.needProvenanceRangeToCharBlockMappings) {
9797
currentCooked_->CompileProvenanceRangeToOffsetMappings(allSources);
9898
}
99+
if (options.showColors) {
100+
allSources.setShowColors(/*showColors=*/true);
101+
}
99102
return sourceFile;
100103
}
101104

flang/lib/Parser/provenance.cpp

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -223,10 +223,26 @@ ProvenanceRange AllSources::AddCompilerInsertion(std::string text) {
223223
return covers;
224224
}
225225

226+
static void EmitPrefix(llvm::raw_ostream &o, llvm::raw_ostream::Colors color,
227+
const std::string &prefix, bool showColors) {
228+
if (prefix.empty()) {
229+
return;
230+
}
231+
if (showColors) {
232+
o.changeColor(color, true);
233+
}
234+
o << prefix;
235+
if (showColors) {
236+
o.resetColor();
237+
}
238+
}
239+
226240
void AllSources::EmitMessage(llvm::raw_ostream &o,
227241
const std::optional<ProvenanceRange> &range, const std::string &message,
242+
const std::string &prefix, llvm::raw_ostream::Colors color,
228243
bool echoSourceLine) const {
229244
if (!range) {
245+
EmitPrefix(o, color, prefix, this->getShowColors());
230246
o << message << '\n';
231247
return;
232248
}
@@ -238,8 +254,9 @@ void AllSources::EmitMessage(llvm::raw_ostream &o,
238254
o << inc.source.path();
239255
std::size_t offset{origin.covers.MemberOffset(range->start())};
240256
SourcePosition pos{inc.source.FindOffsetLineAndColumn(offset)};
241-
o << ':' << pos.line << ':' << pos.column;
242-
o << ": " << message << '\n';
257+
o << ':' << pos.line << ':' << pos.column << ": ";
258+
EmitPrefix(o, color, prefix, this->getShowColors());
259+
o << message << '\n';
243260
if (echoSourceLine) {
244261
const char *text{inc.source.content().data() +
245262
inc.source.GetLineStartOffset(pos.line)};
@@ -269,14 +286,15 @@ void AllSources::EmitMessage(llvm::raw_ostream &o,
269286
}
270287
if (IsValid(origin.replaces)) {
271288
EmitMessage(o, origin.replaces,
272-
inc.isModule ? "used here"s : "included here"s,
289+
inc.isModule ? "used here"s : "included here"s, prefix, color,
273290
echoSourceLine);
274291
}
275292
},
276293
[&](const Macro &mac) {
277-
EmitMessage(o, origin.replaces, message, echoSourceLine);
278294
EmitMessage(
279-
o, mac.definition, "in a macro defined here", echoSourceLine);
295+
o, origin.replaces, message, prefix, color, echoSourceLine);
296+
EmitMessage(o, mac.definition, "in a macro defined here", prefix,
297+
color, echoSourceLine);
280298
if (echoSourceLine) {
281299
o << "that expanded to:\n " << mac.expansion << "\n ";
282300
for (std::size_t j{0};
@@ -286,7 +304,10 @@ void AllSources::EmitMessage(llvm::raw_ostream &o,
286304
o << "^\n";
287305
}
288306
},
289-
[&](const CompilerInsertion &) { o << message << '\n'; },
307+
[&](const CompilerInsertion &) {
308+
EmitPrefix(o, color, prefix, this->getShowColors());
309+
o << message << '\n';
310+
},
290311
},
291312
origin.u);
292313
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
! Test the behaviors of -f{no-}color-diagnostics when emitting parsing
2+
! diagnostics.
3+
! Windows command prompt doesn't support ANSI escape sequences.
4+
! REQUIRES: shell
5+
6+
! RUN: not %flang %s -fcolor-diagnostics 2>&1 \
7+
! RUN: | FileCheck %s --check-prefix=CHECK_CD
8+
! RUN: not %flang %s -fno-color-diagnostics 2>&1 \
9+
! RUN: | FileCheck %s --check-prefix=CHECK_NCD
10+
! RUN: not %flang_fc1 %s -fcolor-diagnostics 2>&1 \
11+
! RUN: | FileCheck %s --check-prefix=CHECK_CD
12+
! RUN: not %flang_fc1 %s 2>&1 | FileCheck %s --check-prefix=CHECK_NCD
13+
14+
! CHECK_CD: {{.*}}[0;1;31merror: {{.*}}[0mexpected '('
15+
16+
! CHECK_NCD: error: expected '('
17+
18+
program m
19+
integer :: i =
20+
end
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
! Test the behaviors of -f{no-}color-diagnostics when emitting scanning
2+
! diagnostics.
3+
! Windows command prompt doesn't support ANSI escape sequences.
4+
! REQUIRES: shell
5+
6+
! RUN: not %flang %s -E -Werror -fcolor-diagnostics 2>&1 \
7+
! RUN: | FileCheck %s --check-prefix=CHECK_CD
8+
! RUN: not %flang %s -E -Werror -fno-color-diagnostics 2>&1 \
9+
! RUN: | FileCheck %s --check-prefix=CHECK_NCD
10+
! RUN: not %flang_fc1 -E -Werror %s -fcolor-diagnostics 2>&1 \
11+
! RUN: | FileCheck %s --check-prefix=CHECK_CD
12+
! RUN: not %flang_fc1 -E -Werror %s 2>&1 | FileCheck %s --check-prefix=CHECK_NCD
13+
14+
! CHECK_CD: {{.*}}[0;1;35mwarning: {{.*}}[0mCharacter in fixed-form label field must be a digit
15+
16+
! CHECK_NCD: warning: Character in fixed-form label field must be a digit
17+
18+
1 continue
19+
end
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
! Test the behaviors of -f{no-}color-diagnostics when emitting semantic
2+
! diagnostics.
3+
! Windows command prompt doesn't support ANSI escape sequences.
4+
! REQUIRES: shell
5+
6+
! RUN: not %flang %s -fcolor-diagnostics 2>&1 \
7+
! RUN: | FileCheck %s --check-prefix=CHECK_CD
8+
! RUN: not %flang %s -fno-color-diagnostics 2>&1 \
9+
! RUN: | FileCheck %s --check-prefix=CHECK_NCD
10+
! RUN: not %flang_fc1 %s -fcolor-diagnostics 2>&1 \
11+
! RUN: | FileCheck %s --check-prefix=CHECK_CD
12+
! RUN: not %flang_fc1 %s 2>&1 | FileCheck %s --check-prefix=CHECK_NCD
13+
14+
! CHECK_CD: {{.*}}[0;1;31merror: {{.*}}[0mMust be a constant value
15+
16+
! CHECK_NCD: error: Must be a constant value
17+
18+
program m
19+
integer :: i = k
20+
end

flang/tools/bbc/bbc.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,8 @@ static mlir::LogicalResult convertFortranSourceToMLIR(
167167
parsing.messages().Emit(llvm::errs(), parsing.allCooked());
168168
if (!parsing.consumedWholeFile()) {
169169
parsing.EmitMessage(llvm::errs(), parsing.finalRestingPlace(),
170-
"parser FAIL (final position)");
170+
"parser FAIL (final position)",
171+
"error: ", llvm::raw_ostream::RED);
171172
return mlir::failure();
172173
}
173174
if ((!parsing.messages().empty() && (parsing.messages().AnyFatalError())) ||

flang/tools/f18-parse-demo/f18-parse-demo.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,7 @@ std::string CompileFortran(
201201
parsing.messages().Emit(llvm::errs(), parsing.allCooked());
202202
if (!parsing.consumedWholeFile()) {
203203
parsing.EmitMessage(llvm::errs(), parsing.finalRestingPlace(),
204-
"parser FAIL (final position)");
204+
"parser FAIL (final position)", "error: ", llvm::raw_ostream::RED);
205205
exitStatus = EXIT_FAILURE;
206206
return {};
207207
}

0 commit comments

Comments
 (0)