Tests?<br><br><div class="gmail_quote">On Mon, Jul 9, 2012 at 7:57 PM, Jordan Rose <span dir="ltr"><<a href="mailto:jordan_rose@apple.com" target="_blank">jordan_rose@apple.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Author: jrose<br>
Date: Mon Jul 9 21:57:03 2012<br>
New Revision: 159978<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=159978&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=159978&view=rev</a><br>
Log:<br>
Allow line numbers on -verify directives.<br>
<br>
// expected-warning@10 {{some text}}<br>
<br>
The line number may be absolute (as above), or relative to the current<br>
line by prefixing the number with either '+' or '-'.<br>
<br>
Patch by Andy Gibbs!<br>
<br>
Modified:<br>
cfe/trunk/include/clang/Basic/DiagnosticFrontendKinds.td<br>
cfe/trunk/include/clang/Basic/SourceManager.h<br>
cfe/trunk/include/clang/Frontend/VerifyDiagnosticConsumer.h<br>
cfe/trunk/lib/Frontend/VerifyDiagnosticConsumer.cpp<br>
<br>
Modified: cfe/trunk/include/clang/Basic/DiagnosticFrontendKinds.td<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticFrontendKinds.td?rev=159978&r1=159977&r2=159978&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticFrontendKinds.td?rev=159978&r1=159977&r2=159978&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/include/clang/Basic/DiagnosticFrontendKinds.td (original)<br>
+++ cfe/trunk/include/clang/Basic/DiagnosticFrontendKinds.td Mon Jul 9 21:57:03 2012<br>
@@ -63,6 +63,8 @@<br>
"unable to open file %0 for serializing diagnostics (%1)">,<br>
InGroup<DiagGroup<"serialized-diagnostics">>;<br>
<br>
+def err_verify_missing_line : Error<<br>
+ "missing or invalid line number following '@' in expected %0">;<br>
def err_verify_missing_start : Error<<br>
"cannot find start ('{{') of expected %0">;<br>
def err_verify_missing_end : Error<<br>
<br>
Modified: cfe/trunk/include/clang/Basic/SourceManager.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/SourceManager.h?rev=159978&r1=159977&r2=159978&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/SourceManager.h?rev=159978&r1=159977&r2=159978&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/include/clang/Basic/SourceManager.h (original)<br>
+++ cfe/trunk/include/clang/Basic/SourceManager.h Mon Jul 9 21:57:03 2012<br>
@@ -36,6 +36,7 @@<br>
#define LLVM_CLANG_SOURCEMANAGER_H<br>
<br>
#include "clang/Basic/LLVM.h"<br>
+#include "clang/Basic/FileManager.h"<br>
#include "clang/Basic/SourceLocation.h"<br>
#include "llvm/Support/Allocator.h"<br>
#include "llvm/Support/DataTypes.h"<br>
@@ -897,6 +898,13 @@<br>
return getFileIDSlow(SLocOffset);<br>
}<br>
<br>
+ /// \brief Return the filename of the file containing a SourceLocation.<br>
+ StringRef getFilename(SourceLocation SpellingLoc) const {<br>
+ if (const FileEntry *F = getFileEntryForID(getFileID(SpellingLoc)))<br>
+ return F->getName();<br>
+ return StringRef();<br>
+ }<br>
+<br>
/// \brief Return the source location corresponding to the first byte of<br>
/// the specified file.<br>
SourceLocation getLocForStartOfFile(FileID FID) const {<br>
<br>
Modified: cfe/trunk/include/clang/Frontend/VerifyDiagnosticConsumer.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/VerifyDiagnosticConsumer.h?rev=159978&r1=159977&r2=159978&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/VerifyDiagnosticConsumer.h?rev=159978&r1=159977&r2=159978&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/include/clang/Frontend/VerifyDiagnosticConsumer.h (original)<br>
+++ cfe/trunk/include/clang/Frontend/VerifyDiagnosticConsumer.h Mon Jul 9 21:57:03 2012<br>
@@ -44,6 +44,15 @@<br>
/// You can place as many diagnostics on one line as you wish. To make the code<br>
/// more readable, you can use slash-newline to separate out the diagnostics.<br>
///<br>
+/// Alternatively, it is possible to specify the line on which the diagnostic<br>
+/// should appear by appending "@<line>" to "expected-<type>", for example:<br>
+///<br>
+/// #warning some text<br>
+/// // expected-warning@10 {{some text}}<br>
+///<br>
+/// The line number may be absolute (as above), or relative to the current<br>
+/// line by prefixing the number with either '+' or '-'.<br>
+///<br>
/// The simple syntax above allows each specification to match exactly one<br>
/// error. You can use the extended syntax to customize this. The extended<br>
/// syntax is "expected-<type> <n> {{diag text}}", where \<type> is one of<br>
@@ -74,13 +83,15 @@<br>
///<br>
class Directive {<br>
public:<br>
- static Directive *create(bool RegexKind, const SourceLocation &Location,<br>
+ static Directive *create(bool RegexKind, SourceLocation DirectiveLoc,<br>
+ SourceLocation DiagnosticLoc,<br>
StringRef Text, unsigned Count);<br>
public:<br>
/// Constant representing one or more matches aka regex "+".<br>
static const unsigned OneOrMoreCount = UINT_MAX;<br>
<br>
- SourceLocation Location;<br>
+ SourceLocation DirectiveLoc;<br>
+ SourceLocation DiagnosticLoc;<br>
const std::string Text;<br>
unsigned Count;<br>
<br>
@@ -94,9 +105,10 @@<br>
virtual bool match(StringRef S) = 0;<br>
<br>
protected:<br>
- Directive(const SourceLocation &Location, StringRef Text,<br>
- unsigned Count)<br>
- : Location(Location), Text(Text), Count(Count) { }<br>
+ Directive(SourceLocation DirectiveLoc, SourceLocation DiagnosticLoc,<br>
+ StringRef Text, unsigned Count)<br>
+ : DirectiveLoc(DirectiveLoc), DiagnosticLoc(DiagnosticLoc),<br>
+ Text(Text), Count(Count) { }<br>
<br>
private:<br>
Directive(const Directive&); // DO NOT IMPLEMENT<br>
<br>
Modified: cfe/trunk/lib/Frontend/VerifyDiagnosticConsumer.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/VerifyDiagnosticConsumer.cpp?rev=159978&r1=159977&r2=159978&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/VerifyDiagnosticConsumer.cpp?rev=159978&r1=159977&r2=159978&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/Frontend/VerifyDiagnosticConsumer.cpp (original)<br>
+++ cfe/trunk/lib/Frontend/VerifyDiagnosticConsumer.cpp Mon Jul 9 21:57:03 2012<br>
@@ -83,9 +83,9 @@<br>
///<br>
class StandardDirective : public Directive {<br>
public:<br>
- StandardDirective(const SourceLocation &Location, StringRef Text,<br>
- unsigned Count)<br>
- : Directive(Location, Text, Count) { }<br>
+ StandardDirective(SourceLocation DirectiveLoc, SourceLocation DiagnosticLoc,<br>
+ StringRef Text, unsigned Count)<br>
+ : Directive(DirectiveLoc, DiagnosticLoc, Text, Count) { }<br>
<br>
virtual bool isValid(std::string &Error) {<br>
// all strings are considered valid; even empty ones<br>
@@ -101,9 +101,9 @@<br>
///<br>
class RegexDirective : public Directive {<br>
public:<br>
- RegexDirective(const SourceLocation &Location, StringRef Text,<br>
- unsigned Count)<br>
- : Directive(Location, Text, Count), Regex(Text) { }<br>
+ RegexDirective(SourceLocation DirectiveLoc, SourceLocation DiagnosticLoc,<br>
+ StringRef Text, unsigned Count)<br>
+ : Directive(DirectiveLoc, DiagnosticLoc, Text, Count), Regex(Text) { }<br>
<br>
virtual bool isValid(std::string &Error) {<br>
if (Regex.isValid(Error))<br>
@@ -195,17 +195,17 @@<br>
SourceLocation Pos, DiagnosticsEngine &Diags) {<br>
// A single comment may contain multiple directives.<br>
for (ParseHelper PH(CommentStart, CommentStart+CommentLen); !PH.Done();) {<br>
- // search for token: expected<br>
+ // Search for token: expected<br>
if (!PH.Search("expected"))<br>
break;<br>
PH.Advance();<br>
<br>
- // next token: -<br>
+ // Next token: -<br>
if (!PH.Next("-"))<br>
continue;<br>
PH.Advance();<br>
<br>
- // next token: { error | warning | note }<br>
+ // Next token: { error | warning | note }<br>
DirectiveList* DL = NULL;<br>
if (PH.Next("error"))<br>
DL = &ED.Errors;<br>
@@ -217,21 +217,53 @@<br>
continue;<br>
PH.Advance();<br>
<br>
- // default directive kind<br>
+ // Default directive kind.<br>
bool RegexKind = false;<br>
const char* KindStr = "string";<br>
<br>
- // next optional token: -<br>
+ // Next optional token: -<br>
if (PH.Next("-re")) {<br>
PH.Advance();<br>
RegexKind = true;<br>
KindStr = "regex";<br>
}<br>
<br>
- // skip optional whitespace<br>
+ // Next optional token: @<br>
+ SourceLocation ExpectedLoc;<br>
+ if (!PH.Next("@")) {<br>
+ ExpectedLoc = Pos;<br>
+ } else {<br>
+ PH.Advance();<br>
+ unsigned Line = 0;<br>
+ bool FoundPlus = PH.Next("+");<br>
+ if (FoundPlus || PH.Next("-")) {<br>
+ // Relative to current line.<br>
+ PH.Advance();<br>
+ bool Invalid = false;<br>
+ unsigned ExpectedLine = SM.getSpellingLineNumber(Pos, &Invalid);<br>
+ if (!Invalid && PH.Next(Line) && (FoundPlus || Line < ExpectedLine)) {<br>
+ if (FoundPlus) ExpectedLine += Line;<br>
+ else ExpectedLine -= Line;<br>
+ ExpectedLoc = SM.translateLineCol(SM.getFileID(Pos), ExpectedLine, 1);<br>
+ }<br>
+ } else {<br>
+ // Absolute line number.<br>
+ if (PH.Next(Line) && Line > 0)<br>
+ ExpectedLoc = SM.translateLineCol(SM.getFileID(Pos), Line, 1);<br>
+ }<br>
+<br>
+ if (ExpectedLoc.isInvalid()) {<br>
+ Diags.Report(Pos.getLocWithOffset(PH.C-PH.Begin),<br>
+ diag::err_verify_missing_line) << KindStr;<br>
+ continue;<br>
+ }<br>
+ PH.Advance();<br>
+ }<br>
+<br>
+ // Skip optional whitespace.<br>
PH.SkipWhitespace();<br>
<br>
- // next optional token: positive integer or a '+'.<br>
+ // Next optional token: positive integer or a '+'.<br>
unsigned Count = 1;<br>
if (PH.Next(Count))<br>
PH.Advance();<br>
@@ -240,10 +272,10 @@<br>
PH.Advance();<br>
}<br>
<br>
- // skip optional whitespace<br>
+ // Skip optional whitespace.<br>
PH.SkipWhitespace();<br>
<br>
- // next token: {{<br>
+ // Next token: {{<br>
if (!PH.Next("{{")) {<br>
Diags.Report(Pos.getLocWithOffset(PH.C-PH.Begin),<br>
diag::err_verify_missing_start) << KindStr;<br>
@@ -252,7 +284,7 @@<br>
PH.Advance();<br>
const char* const ContentBegin = PH.C; // mark content begin<br>
<br>
- // search for token: }}<br>
+ // Search for token: }}<br>
if (!PH.Search("}}")) {<br>
Diags.Report(Pos.getLocWithOffset(PH.C-PH.Begin),<br>
diag::err_verify_missing_end) << KindStr;<br>
@@ -261,7 +293,7 @@<br>
const char* const ContentEnd = PH.P; // mark content end<br>
PH.Advance();<br>
<br>
- // build directive text; convert \n to newlines<br>
+ // Build directive text; convert \n to newlines.<br>
std::string Text;<br>
StringRef NewlineStr = "\\n";<br>
StringRef Content(ContentBegin, ContentEnd-ContentBegin);<br>
@@ -275,8 +307,8 @@<br>
if (Text.empty())<br>
Text.assign(ContentBegin, ContentEnd);<br>
<br>
- // construct new directive<br>
- Directive *D = Directive::create(RegexKind, Pos, Text, Count);<br>
+ // Construct new directive.<br>
+ Directive *D = Directive::create(RegexKind, Pos, ExpectedLoc, Text, Count);<br>
std::string Error;<br>
if (D->isValid(Error))<br>
DL->push_back(D);<br>
@@ -318,15 +350,12 @@<br>
};<br>
}<br>
<br>
-/// PrintProblem - This takes a diagnostic map of the delta between expected and<br>
-/// seen diagnostics. If there's anything in it, then something unexpected<br>
-/// happened. Print the map out in a nice format and return "true". If the map<br>
-/// is empty and we're not going to print things, then return "false".<br>
-///<br>
-static unsigned PrintProblem(DiagnosticsEngine &Diags, SourceManager *SourceMgr,<br>
- const_diag_iterator diag_begin,<br>
- const_diag_iterator diag_end,<br>
- const char *Kind, bool Expected) {<br>
+/// \brief Takes a list of diagnostics that have been generated but not matched<br>
+/// by an expected-* directive and produces a diagnostic to the user from this.<br>
+static unsigned PrintUnexpected(DiagnosticsEngine &Diags, SourceManager *SourceMgr,<br>
+ const_diag_iterator diag_begin,<br>
+ const_diag_iterator diag_end,<br>
+ const char *Kind) {<br>
if (diag_begin == diag_end) return 0;<br>
<br>
SmallString<256> Fmt;<br>
@@ -340,29 +369,31 @@<br>
}<br>
<br>
Diags.Report(diag::err_verify_inconsistent_diags)<br>
- << Kind << !Expected << OS.str();<br>
+ << Kind << /*Unexpected=*/true << OS.str();<br>
return std::distance(diag_begin, diag_end);<br>
}<br>
<br>
-static unsigned PrintProblem(DiagnosticsEngine &Diags, SourceManager *SourceMgr,<br>
- DirectiveList &DL, const char *Kind,<br>
- bool Expected) {<br>
+/// \brief Takes a list of diagnostics that were expected to have been generated<br>
+/// but were not and produces a diagnostic to the user from this.<br>
+static unsigned PrintExpected(DiagnosticsEngine &Diags, SourceManager &SourceMgr,<br>
+ DirectiveList &DL, const char *Kind) {<br>
if (DL.empty())<br>
return 0;<br>
<br>
SmallString<256> Fmt;<br>
llvm::raw_svector_ostream OS(Fmt);<br>
for (DirectiveList::iterator I = DL.begin(), E = DL.end(); I != E; ++I) {<br>
- Directive& D = **I;<br>
- if (D.Location.isInvalid() || !SourceMgr)<br>
- OS << "\n (frontend)";<br>
- else<br>
- OS << "\n Line " << SourceMgr->getPresumedLineNumber(D.Location);<br>
+ Directive &D = **I;<br>
+ OS << "\n Line " << SourceMgr.getPresumedLineNumber(D.DiagnosticLoc);<br>
+ if (D.DirectiveLoc != D.DiagnosticLoc)<br>
+ OS << " (directive at "<br>
+ << SourceMgr.getFilename(D.DirectiveLoc) << ":"<br>
+ << SourceMgr.getPresumedLineNumber(D.DirectiveLoc) << ")";<br>
OS << ": " << D.Text;<br>
}<br>
<br>
Diags.Report(diag::err_verify_inconsistent_diags)<br>
- << Kind << !Expected << OS.str();<br>
+ << Kind << /*Unexpected=*/false << OS.str();<br>
return DL.size();<br>
}<br>
<br>
@@ -379,7 +410,7 @@<br>
<br>
for (DirectiveList::iterator I = Left.begin(), E = Left.end(); I != E; ++I) {<br>
Directive& D = **I;<br>
- unsigned LineNo1 = SourceMgr.getPresumedLineNumber(D.Location);<br>
+ unsigned LineNo1 = SourceMgr.getPresumedLineNumber(D.DiagnosticLoc);<br>
bool FoundOnce = false;<br>
<br>
for (unsigned i = 0; i < D.Count; ++i) {<br>
@@ -410,9 +441,8 @@<br>
}<br>
}<br>
// Now all that's left in Right are those that were not matched.<br>
- unsigned num = PrintProblem(Diags, &SourceMgr, LeftOnly, Label, true);<br>
- num += PrintProblem(Diags, &SourceMgr, Right.begin(), Right.end(),<br>
- Label, false);<br>
+ unsigned num = PrintExpected(Diags, SourceMgr, LeftOnly, Label);<br>
+ num += PrintUnexpected(Diags, &SourceMgr, Right.begin(), Right.end(), Label);<br>
return num;<br>
}<br>
<br>
@@ -472,15 +502,12 @@<br>
// Check that the expected diagnostics occurred.<br>
NumErrors += CheckResults(Diags, SM, *Buffer, ED);<br>
} else {<br>
- NumErrors += (PrintProblem(Diags, 0,<br>
- Buffer->err_begin(), Buffer->err_end(),<br>
- "error", false) +<br>
- PrintProblem(Diags, 0,<br>
- Buffer->warn_begin(), Buffer->warn_end(),<br>
- "warn", false) +<br>
- PrintProblem(Diags, 0,<br>
- Buffer->note_begin(), Buffer->note_end(),<br>
- "note", false));<br>
+ NumErrors += (PrintUnexpected(Diags, 0, Buffer->err_begin(),<br>
+ Buffer->err_end(), "error") +<br>
+ PrintUnexpected(Diags, 0, Buffer->warn_begin(),<br>
+ Buffer->warn_end(), "warn") +<br>
+ PrintUnexpected(Diags, 0, Buffer->note_begin(),<br>
+ Buffer->note_end(), "note"));<br>
}<br>
<br>
Diags.takeClient();<br>
@@ -498,9 +525,10 @@<br>
return new VerifyDiagnosticConsumer(Diags);<br>
}<br>
<br>
-Directive *Directive::create(bool RegexKind, const SourceLocation &Location,<br>
- StringRef Text, unsigned Count) {<br>
+Directive *Directive::create(bool RegexKind, SourceLocation DirectiveLoc,<br>
+ SourceLocation DiagnosticLoc, StringRef Text,<br>
+ unsigned Count) {<br>
if (RegexKind)<br>
- return new RegexDirective(Location, Text, Count);<br>
- return new StandardDirective(Location, Text, Count);<br>
+ return new RegexDirective(DirectiveLoc, DiagnosticLoc, Text, Count);<br>
+ return new StandardDirective(DirectiveLoc, DiagnosticLoc, Text, Count);<br>
}<br>
<br>
<br>
_______________________________________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@cs.uiuc.edu">cfe-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits</a><br>
</blockquote></div><br>