Skip to content

Commit 05eedf1

Browse files
Alexandre Ramesjkorous-apple
authored andcommitted
[clang][VerifyDiagnosticConsumer] Support filename wildcards
Differential Revision: https://reviews.llvm.org/D72100
1 parent 0363ae9 commit 05eedf1

File tree

4 files changed

+81
-43
lines changed

4 files changed

+81
-43
lines changed

clang/include/clang/Frontend/VerifyDiagnosticConsumer.h

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -190,11 +190,10 @@ class VerifyDiagnosticConsumer: public DiagnosticConsumer,
190190
///
191191
class Directive {
192192
public:
193-
static std::unique_ptr<Directive> create(bool RegexKind,
194-
SourceLocation DirectiveLoc,
195-
SourceLocation DiagnosticLoc,
196-
bool MatchAnyLine, StringRef Text,
197-
unsigned Min, unsigned Max);
193+
static std::unique_ptr<Directive>
194+
create(bool RegexKind, SourceLocation DirectiveLoc,
195+
SourceLocation DiagnosticLoc, bool MatchAnyFileAndLine,
196+
bool MatchAnyLine, StringRef Text, unsigned Min, unsigned Max);
198197

199198
public:
200199
/// Constant representing n or more matches.
@@ -205,6 +204,7 @@ class VerifyDiagnosticConsumer: public DiagnosticConsumer,
205204
const std::string Text;
206205
unsigned Min, Max;
207206
bool MatchAnyLine;
207+
bool MatchAnyFileAndLine; // `MatchAnyFileAndLine` implies `MatchAnyLine`.
208208

209209
Directive(const Directive &) = delete;
210210
Directive &operator=(const Directive &) = delete;
@@ -219,9 +219,11 @@ class VerifyDiagnosticConsumer: public DiagnosticConsumer,
219219

220220
protected:
221221
Directive(SourceLocation DirectiveLoc, SourceLocation DiagnosticLoc,
222-
bool MatchAnyLine, StringRef Text, unsigned Min, unsigned Max)
223-
: DirectiveLoc(DirectiveLoc), DiagnosticLoc(DiagnosticLoc),
224-
Text(Text), Min(Min), Max(Max), MatchAnyLine(MatchAnyLine) {
222+
bool MatchAnyFileAndLine, bool MatchAnyLine, StringRef Text,
223+
unsigned Min, unsigned Max)
224+
: DirectiveLoc(DirectiveLoc), DiagnosticLoc(DiagnosticLoc), Text(Text),
225+
Min(Min), Max(Max), MatchAnyLine(MatchAnyLine || MatchAnyFileAndLine),
226+
MatchAnyFileAndLine(MatchAnyFileAndLine) {
225227
assert(!DirectiveLoc.isInvalid() && "DirectiveLoc is invalid!");
226228
assert((!DiagnosticLoc.isInvalid() || MatchAnyLine) &&
227229
"DiagnosticLoc is invalid!");

clang/lib/Frontend/VerifyDiagnosticConsumer.cpp

Lines changed: 56 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -89,9 +89,10 @@ namespace {
8989
class StandardDirective : public Directive {
9090
public:
9191
StandardDirective(SourceLocation DirectiveLoc, SourceLocation DiagnosticLoc,
92-
bool MatchAnyLine, StringRef Text, unsigned Min,
93-
unsigned Max)
94-
: Directive(DirectiveLoc, DiagnosticLoc, MatchAnyLine, Text, Min, Max) {}
92+
bool MatchAnyFileAndLine, bool MatchAnyLine, StringRef Text,
93+
unsigned Min, unsigned Max)
94+
: Directive(DirectiveLoc, DiagnosticLoc, MatchAnyFileAndLine,
95+
MatchAnyLine, Text, Min, Max) {}
9596

9697
bool isValid(std::string &Error) override {
9798
// all strings are considered valid; even empty ones
@@ -107,9 +108,10 @@ class StandardDirective : public Directive {
107108
class RegexDirective : public Directive {
108109
public:
109110
RegexDirective(SourceLocation DirectiveLoc, SourceLocation DiagnosticLoc,
110-
bool MatchAnyLine, StringRef Text, unsigned Min, unsigned Max,
111-
StringRef RegexStr)
112-
: Directive(DirectiveLoc, DiagnosticLoc, MatchAnyLine, Text, Min, Max),
111+
bool MatchAnyFileAndLine, bool MatchAnyLine, StringRef Text,
112+
unsigned Min, unsigned Max, StringRef RegexStr)
113+
: Directive(DirectiveLoc, DiagnosticLoc, MatchAnyFileAndLine,
114+
MatchAnyLine, Text, Min, Max),
113115
Regex(RegexStr) {}
114116

115117
bool isValid(std::string &Error) override {
@@ -294,11 +296,13 @@ struct UnattachedDirective {
294296
// Attach the specified directive to the line of code indicated by
295297
// \p ExpectedLoc.
296298
void attachDirective(DiagnosticsEngine &Diags, const UnattachedDirective &UD,
297-
SourceLocation ExpectedLoc, bool MatchAnyLine = false) {
299+
SourceLocation ExpectedLoc,
300+
bool MatchAnyFileAndLine = false,
301+
bool MatchAnyLine = false) {
298302
// Construct new directive.
299-
std::unique_ptr<Directive> D =
300-
Directive::create(UD.RegexKind, UD.DirectivePos, ExpectedLoc,
301-
MatchAnyLine, UD.Text, UD.Min, UD.Max);
303+
std::unique_ptr<Directive> D = Directive::create(
304+
UD.RegexKind, UD.DirectivePos, ExpectedLoc, MatchAnyFileAndLine,
305+
MatchAnyLine, UD.Text, UD.Min, UD.Max);
302306

303307
std::string Error;
304308
if (!D->isValid(Error)) {
@@ -498,6 +502,7 @@ static bool ParseDirective(StringRef S, ExpectedData *ED, SourceManager &SM,
498502
// Next optional token: @
499503
SourceLocation ExpectedLoc;
500504
StringRef Marker;
505+
bool MatchAnyFileAndLine = false;
501506
bool MatchAnyLine = false;
502507
if (!PH.Next("@")) {
503508
ExpectedLoc = Pos;
@@ -526,26 +531,39 @@ static bool ParseDirective(StringRef S, ExpectedData *ED, SourceManager &SM,
526531
StringRef Filename(PH.C, PH.P-PH.C);
527532
PH.Advance();
528533

529-
// Lookup file via Preprocessor, like a #include.
530-
const DirectoryLookup *CurDir;
531-
Optional<FileEntryRef> File =
532-
PP->LookupFile(Pos, Filename, false, nullptr, nullptr, CurDir,
533-
nullptr, nullptr, nullptr, nullptr, nullptr);
534-
if (!File) {
535-
Diags.Report(Pos.getLocWithOffset(PH.C-PH.Begin),
536-
diag::err_verify_missing_file) << Filename << KindStr;
537-
continue;
538-
}
539-
540-
const FileEntry *FE = &File->getFileEntry();
541-
if (SM.translateFile(FE).isInvalid())
542-
SM.createFileID(FE, Pos, SrcMgr::C_User);
543-
544-
if (PH.Next(Line) && Line > 0)
545-
ExpectedLoc = SM.translateFileLineCol(FE, Line, 1);
546-
else if (PH.Next("*")) {
534+
if (Filename == "*") {
535+
MatchAnyFileAndLine = true;
536+
if (!PH.Next("*")) {
537+
Diags.Report(Pos.getLocWithOffset(PH.C - PH.Begin),
538+
diag::err_verify_missing_line)
539+
<< "'*'";
540+
continue;
541+
}
547542
MatchAnyLine = true;
548-
ExpectedLoc = SM.translateFileLineCol(FE, 1, 1);
543+
ExpectedLoc = SourceLocation();
544+
} else {
545+
// Lookup file via Preprocessor, like a #include.
546+
const DirectoryLookup *CurDir;
547+
Optional<FileEntryRef> File =
548+
PP->LookupFile(Pos, Filename, false, nullptr, nullptr, CurDir,
549+
nullptr, nullptr, nullptr, nullptr, nullptr);
550+
if (!File) {
551+
Diags.Report(Pos.getLocWithOffset(PH.C - PH.Begin),
552+
diag::err_verify_missing_file)
553+
<< Filename << KindStr;
554+
continue;
555+
}
556+
557+
const FileEntry *FE = &File->getFileEntry();
558+
if (SM.translateFile(FE).isInvalid())
559+
SM.createFileID(FE, Pos, SrcMgr::C_User);
560+
561+
if (PH.Next(Line) && Line > 0)
562+
ExpectedLoc = SM.translateFileLineCol(FE, Line, 1);
563+
else if (PH.Next("*")) {
564+
MatchAnyLine = true;
565+
ExpectedLoc = SM.translateFileLineCol(FE, 1, 1);
566+
}
549567
}
550568
} else if (PH.Next("*")) {
551569
MatchAnyLine = true;
@@ -631,7 +649,7 @@ static bool ParseDirective(StringRef S, ExpectedData *ED, SourceManager &SM,
631649
}
632650

633651
if (Marker.empty())
634-
attachDirective(Diags, D, ExpectedLoc, MatchAnyLine);
652+
attachDirective(Diags, D, ExpectedLoc, MatchAnyFileAndLine, MatchAnyLine);
635653
else
636654
Markers.addDirective(Marker, D);
637655
FoundDirective = true;
@@ -877,7 +895,7 @@ static unsigned PrintExpected(DiagnosticsEngine &Diags,
877895
SmallString<256> Fmt;
878896
llvm::raw_svector_ostream OS(Fmt);
879897
for (const auto *D : DL) {
880-
if (D->DiagnosticLoc.isInvalid())
898+
if (D->DiagnosticLoc.isInvalid() || D->MatchAnyFileAndLine)
881899
OS << "\n File *";
882900
else
883901
OS << "\n File " << SourceMgr.getFilename(D->DiagnosticLoc);
@@ -937,7 +955,7 @@ static unsigned CheckLists(DiagnosticsEngine &Diags, SourceManager &SourceMgr,
937955
continue;
938956
}
939957

940-
if (!D.DiagnosticLoc.isInvalid() &&
958+
if (!D.DiagnosticLoc.isInvalid() && !D.MatchAnyFileAndLine &&
941959
!IsFromSameFile(SourceMgr, D.DiagnosticLoc, II->first))
942960
continue;
943961

@@ -1114,11 +1132,13 @@ void VerifyDiagnosticConsumer::CheckDiagnostics() {
11141132
std::unique_ptr<Directive> Directive::create(bool RegexKind,
11151133
SourceLocation DirectiveLoc,
11161134
SourceLocation DiagnosticLoc,
1135+
bool MatchAnyFileAndLine,
11171136
bool MatchAnyLine, StringRef Text,
11181137
unsigned Min, unsigned Max) {
11191138
if (!RegexKind)
11201139
return std::make_unique<StandardDirective>(DirectiveLoc, DiagnosticLoc,
1121-
MatchAnyLine, Text, Min, Max);
1140+
MatchAnyFileAndLine,
1141+
MatchAnyLine, Text, Min, Max);
11221142

11231143
// Parse the directive into a regular expression.
11241144
std::string RegexStr;
@@ -1143,6 +1163,7 @@ std::unique_ptr<Directive> Directive::create(bool RegexKind,
11431163
}
11441164
}
11451165

1146-
return std::make_unique<RegexDirective>(
1147-
DirectiveLoc, DiagnosticLoc, MatchAnyLine, Text, Min, Max, RegexStr);
1166+
return std::make_unique<RegexDirective>(DirectiveLoc, DiagnosticLoc,
1167+
MatchAnyFileAndLine, MatchAnyLine,
1168+
Text, Min, Max, RegexStr);
11481169
}

clang/test/Frontend/verify-any-file.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// RUN: not %clang_cc1 -verify %s 2>&1 | FileCheck %s
2+
3+
#include "verify-any-file.h"
4+
// expected-error@*:* {{unknown type name 'unexpected'}}
5+
6+
// expected-error@*:* {{missing error}}
7+
8+
// expected-error@*:123 {{invalid line : "*" required}}
9+
//
10+
// CHECK: error: 'error' diagnostics expected but not seen:
11+
// CHECK-NEXT: File * Line * (directive at {{.*}}verify-any-file.c:6): missing error
12+
// CHECK-NEXT: error: 'error' diagnostics seen but not expected:
13+
// CHECK-NEXT: File {{.*}}verify-any-file.c Line 8: missing or invalid line number following '@' in expected '*'
14+
// CHECK-NEXT: 2 errors generated.

clang/test/Frontend/verify-any-file.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
unexpected var;

0 commit comments

Comments
 (0)