Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cherry-pick 05eedf1f5b449ae42f5493576164b0f9a001646c #1230

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 10 additions & 8 deletions clang/include/clang/Frontend/VerifyDiagnosticConsumer.h
Original file line number Diff line number Diff line change
Expand Up @@ -189,11 +189,10 @@ class VerifyDiagnosticConsumer: public DiagnosticConsumer,
///
class Directive {
public:
static std::unique_ptr<Directive> create(bool RegexKind,
SourceLocation DirectiveLoc,
SourceLocation DiagnosticLoc,
bool MatchAnyLine, StringRef Text,
unsigned Min, unsigned Max);
static std::unique_ptr<Directive>
create(bool RegexKind, SourceLocation DirectiveLoc,
SourceLocation DiagnosticLoc, bool MatchAnyFileAndLine,
bool MatchAnyLine, StringRef Text, unsigned Min, unsigned Max);

public:
/// Constant representing n or more matches.
Expand All @@ -204,6 +203,7 @@ class VerifyDiagnosticConsumer: public DiagnosticConsumer,
const std::string Text;
unsigned Min, Max;
bool MatchAnyLine;
bool MatchAnyFileAndLine; // `MatchAnyFileAndLine` implies `MatchAnyLine`.

Directive(const Directive &) = delete;
Directive &operator=(const Directive &) = delete;
Expand All @@ -218,9 +218,11 @@ class VerifyDiagnosticConsumer: public DiagnosticConsumer,

protected:
Directive(SourceLocation DirectiveLoc, SourceLocation DiagnosticLoc,
bool MatchAnyLine, StringRef Text, unsigned Min, unsigned Max)
: DirectiveLoc(DirectiveLoc), DiagnosticLoc(DiagnosticLoc),
Text(Text), Min(Min), Max(Max), MatchAnyLine(MatchAnyLine) {
bool MatchAnyFileAndLine, bool MatchAnyLine, StringRef Text,
unsigned Min, unsigned Max)
: DirectiveLoc(DirectiveLoc), DiagnosticLoc(DiagnosticLoc), Text(Text),
Min(Min), Max(Max), MatchAnyLine(MatchAnyLine || MatchAnyFileAndLine),
MatchAnyFileAndLine(MatchAnyFileAndLine) {
assert(!DirectiveLoc.isInvalid() && "DirectiveLoc is invalid!");
assert((!DiagnosticLoc.isInvalid() || MatchAnyLine) &&
"DiagnosticLoc is invalid!");
Expand Down
91 changes: 56 additions & 35 deletions clang/lib/Frontend/VerifyDiagnosticConsumer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,9 +89,10 @@ namespace {
class StandardDirective : public Directive {
public:
StandardDirective(SourceLocation DirectiveLoc, SourceLocation DiagnosticLoc,
bool MatchAnyLine, StringRef Text, unsigned Min,
unsigned Max)
: Directive(DirectiveLoc, DiagnosticLoc, MatchAnyLine, Text, Min, Max) {}
bool MatchAnyFileAndLine, bool MatchAnyLine, StringRef Text,
unsigned Min, unsigned Max)
: Directive(DirectiveLoc, DiagnosticLoc, MatchAnyFileAndLine,
MatchAnyLine, Text, Min, Max) {}

bool isValid(std::string &Error) override {
// all strings are considered valid; even empty ones
Expand All @@ -107,9 +108,10 @@ class StandardDirective : public Directive {
class RegexDirective : public Directive {
public:
RegexDirective(SourceLocation DirectiveLoc, SourceLocation DiagnosticLoc,
bool MatchAnyLine, StringRef Text, unsigned Min, unsigned Max,
StringRef RegexStr)
: Directive(DirectiveLoc, DiagnosticLoc, MatchAnyLine, Text, Min, Max),
bool MatchAnyFileAndLine, bool MatchAnyLine, StringRef Text,
unsigned Min, unsigned Max, StringRef RegexStr)
: Directive(DirectiveLoc, DiagnosticLoc, MatchAnyFileAndLine,
MatchAnyLine, Text, Min, Max),
Regex(RegexStr) {}

bool isValid(std::string &Error) override {
Expand Down Expand Up @@ -294,11 +296,13 @@ struct UnattachedDirective {
// Attach the specified directive to the line of code indicated by
// \p ExpectedLoc.
void attachDirective(DiagnosticsEngine &Diags, const UnattachedDirective &UD,
SourceLocation ExpectedLoc, bool MatchAnyLine = false) {
SourceLocation ExpectedLoc,
bool MatchAnyFileAndLine = false,
bool MatchAnyLine = false) {
// Construct new directive.
std::unique_ptr<Directive> D =
Directive::create(UD.RegexKind, UD.DirectivePos, ExpectedLoc,
MatchAnyLine, UD.Text, UD.Min, UD.Max);
std::unique_ptr<Directive> D = Directive::create(
UD.RegexKind, UD.DirectivePos, ExpectedLoc, MatchAnyFileAndLine,
MatchAnyLine, UD.Text, UD.Min, UD.Max);

std::string Error;
if (!D->isValid(Error)) {
Expand Down Expand Up @@ -498,6 +502,7 @@ static bool ParseDirective(StringRef S, ExpectedData *ED, SourceManager &SM,
// Next optional token: @
SourceLocation ExpectedLoc;
StringRef Marker;
bool MatchAnyFileAndLine = false;
bool MatchAnyLine = false;
if (!PH.Next("@")) {
ExpectedLoc = Pos;
Expand Down Expand Up @@ -526,26 +531,39 @@ static bool ParseDirective(StringRef S, ExpectedData *ED, SourceManager &SM,
StringRef Filename(PH.C, PH.P-PH.C);
PH.Advance();

// Lookup file via Preprocessor, like a #include.
const DirectoryLookup *CurDir;
Optional<FileEntryRef> File =
PP->LookupFile(Pos, Filename, false, nullptr, nullptr, CurDir,
nullptr, nullptr, nullptr, nullptr, nullptr);
if (!File) {
Diags.Report(Pos.getLocWithOffset(PH.C-PH.Begin),
diag::err_verify_missing_file) << Filename << KindStr;
continue;
}

const FileEntry *FE = &File->getFileEntry();
if (SM.translateFile(FE).isInvalid())
SM.createFileID(FE, Pos, SrcMgr::C_User);

if (PH.Next(Line) && Line > 0)
ExpectedLoc = SM.translateFileLineCol(FE, Line, 1);
else if (PH.Next("*")) {
if (Filename == "*") {
MatchAnyFileAndLine = true;
if (!PH.Next("*")) {
Diags.Report(Pos.getLocWithOffset(PH.C - PH.Begin),
diag::err_verify_missing_line)
<< "'*'";
continue;
}
MatchAnyLine = true;
ExpectedLoc = SM.translateFileLineCol(FE, 1, 1);
ExpectedLoc = SourceLocation();
} else {
// Lookup file via Preprocessor, like a #include.
const DirectoryLookup *CurDir;
Optional<FileEntryRef> File =
PP->LookupFile(Pos, Filename, false, nullptr, nullptr, CurDir,
nullptr, nullptr, nullptr, nullptr, nullptr);
if (!File) {
Diags.Report(Pos.getLocWithOffset(PH.C - PH.Begin),
diag::err_verify_missing_file)
<< Filename << KindStr;
continue;
}

const FileEntry *FE = &File->getFileEntry();
if (SM.translateFile(FE).isInvalid())
SM.createFileID(FE, Pos, SrcMgr::C_User);

if (PH.Next(Line) && Line > 0)
ExpectedLoc = SM.translateFileLineCol(FE, Line, 1);
else if (PH.Next("*")) {
MatchAnyLine = true;
ExpectedLoc = SM.translateFileLineCol(FE, 1, 1);
}
}
} else if (PH.Next("*")) {
MatchAnyLine = true;
Expand Down Expand Up @@ -631,7 +649,7 @@ static bool ParseDirective(StringRef S, ExpectedData *ED, SourceManager &SM,
}

if (Marker.empty())
attachDirective(Diags, D, ExpectedLoc, MatchAnyLine);
attachDirective(Diags, D, ExpectedLoc, MatchAnyFileAndLine, MatchAnyLine);
else
Markers.addDirective(Marker, D);
FoundDirective = true;
Expand Down Expand Up @@ -877,7 +895,7 @@ static unsigned PrintExpected(DiagnosticsEngine &Diags,
SmallString<256> Fmt;
llvm::raw_svector_ostream OS(Fmt);
for (const auto *D : DL) {
if (D->DiagnosticLoc.isInvalid())
if (D->DiagnosticLoc.isInvalid() || D->MatchAnyFileAndLine)
OS << "\n File *";
else
OS << "\n File " << SourceMgr.getFilename(D->DiagnosticLoc);
Expand Down Expand Up @@ -937,7 +955,7 @@ static unsigned CheckLists(DiagnosticsEngine &Diags, SourceManager &SourceMgr,
continue;
}

if (!D.DiagnosticLoc.isInvalid() &&
if (!D.DiagnosticLoc.isInvalid() && !D.MatchAnyFileAndLine &&
!IsFromSameFile(SourceMgr, D.DiagnosticLoc, II->first))
continue;

Expand Down Expand Up @@ -1114,11 +1132,13 @@ void VerifyDiagnosticConsumer::CheckDiagnostics() {
std::unique_ptr<Directive> Directive::create(bool RegexKind,
SourceLocation DirectiveLoc,
SourceLocation DiagnosticLoc,
bool MatchAnyFileAndLine,
bool MatchAnyLine, StringRef Text,
unsigned Min, unsigned Max) {
if (!RegexKind)
return std::make_unique<StandardDirective>(DirectiveLoc, DiagnosticLoc,
MatchAnyLine, Text, Min, Max);
MatchAnyFileAndLine,
MatchAnyLine, Text, Min, Max);

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

return std::make_unique<RegexDirective>(
DirectiveLoc, DiagnosticLoc, MatchAnyLine, Text, Min, Max, RegexStr);
return std::make_unique<RegexDirective>(DirectiveLoc, DiagnosticLoc,
MatchAnyFileAndLine, MatchAnyLine,
Text, Min, Max, RegexStr);
}
14 changes: 14 additions & 0 deletions clang/test/Frontend/verify-any-file.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// RUN: not %clang_cc1 -verify %s 2>&1 | FileCheck %s

#include "verify-any-file.h"
// expected-error@*:* {{unknown type name 'unexpected'}}

// expected-error@*:* {{missing error}}

// expected-error@*:123 {{invalid line : "*" required}}
//
// CHECK: error: 'error' diagnostics expected but not seen:
// CHECK-NEXT: File * Line * (directive at {{.*}}verify-any-file.c:6): missing error
// CHECK-NEXT: error: 'error' diagnostics seen but not expected:
// CHECK-NEXT: File {{.*}}verify-any-file.c Line 8: missing or invalid line number following '@' in expected '*'
// CHECK-NEXT: 2 errors generated.
1 change: 1 addition & 0 deletions clang/test/Frontend/verify-any-file.h
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
unexpected var;