forked from OSchip/llvm-project
Allow -verify directives to specify a min and max count, not just "+".
void f(); // expected-note 0+ {{previous declaration is here}} void g(); // expected-note 0-1 {{previous declaration is here}} The old "+" syntax is still an alias for "1+", and single numbers still work. Patch by Andy Gibbs! llvm-svn: 159979
This commit is contained in:
parent
e1572eb3e2
commit
b8b2ca6ffb
|
@ -65,6 +65,8 @@ def warn_fe_serialized_diag_failure : Warning<
|
|||
|
||||
def err_verify_missing_line : Error<
|
||||
"missing or invalid line number following '@' in expected %0">;
|
||||
def err_verify_invalid_range : Error<
|
||||
"invalid range following '-' in expected %0">;
|
||||
def err_verify_missing_start : Error<
|
||||
"cannot find start ('{{') of expected %0">;
|
||||
def err_verify_missing_end : Error<
|
||||
|
|
|
@ -47,8 +47,10 @@ class TextDiagnosticBuffer;
|
|||
/// Alternatively, it is possible to specify the line on which the diagnostic
|
||||
/// should appear by appending "@<line>" to "expected-<type>", for example:
|
||||
///
|
||||
/// \code
|
||||
/// #warning some text
|
||||
/// // expected-warning@10 {{some text}}
|
||||
/// \endcode
|
||||
///
|
||||
/// The line number may be absolute (as above), or relative to the current
|
||||
/// line by prefixing the number with either '+' or '-'.
|
||||
|
@ -63,6 +65,31 @@ class TextDiagnosticBuffer;
|
|||
/// void f(); // expected-note 2 {{previous declaration is here}}
|
||||
/// \endcode
|
||||
///
|
||||
/// Where the diagnostic is expected to occur a minimum number of times, this
|
||||
/// can be specified by appending a '+' to the number. Example:
|
||||
///
|
||||
/// \code
|
||||
/// void f(); // expected-note 0+ {{previous declaration is here}}
|
||||
/// void g(); // expected-note 1+ {{previous declaration is here}}
|
||||
/// \endcode
|
||||
///
|
||||
/// In the first example, the diagnostic becomes optional, i.e. it will be
|
||||
/// swallowed if it occurs, but will not generate an error if it does not
|
||||
/// occur. In the second example, the diagnostic must occur at least once.
|
||||
/// As a short-hand, "one or more" can be specified simply by '+'. Example:
|
||||
///
|
||||
/// \code
|
||||
/// void g(); // expected-note + {{previous declaration is here}}
|
||||
/// \endcode
|
||||
///
|
||||
/// A range can also be specified by "<n>-<m>". Example:
|
||||
///
|
||||
/// \code
|
||||
/// void f(); // expected-note 0-1 {{previous declaration is here}}
|
||||
/// \endcode
|
||||
///
|
||||
/// In this example, the diagnostic may appear only once, if at all.
|
||||
///
|
||||
/// Regex matching mode may be selected by appending '-re' to type. Example:
|
||||
///
|
||||
/// expected-error-re
|
||||
|
@ -85,15 +112,15 @@ public:
|
|||
public:
|
||||
static Directive *create(bool RegexKind, SourceLocation DirectiveLoc,
|
||||
SourceLocation DiagnosticLoc,
|
||||
StringRef Text, unsigned Count);
|
||||
StringRef Text, unsigned Min, unsigned Max);
|
||||
public:
|
||||
/// Constant representing one or more matches aka regex "+".
|
||||
static const unsigned OneOrMoreCount = UINT_MAX;
|
||||
/// Constant representing n or more matches.
|
||||
static const unsigned MaxCount = UINT_MAX;
|
||||
|
||||
SourceLocation DirectiveLoc;
|
||||
SourceLocation DiagnosticLoc;
|
||||
const std::string Text;
|
||||
unsigned Count;
|
||||
unsigned Min, Max;
|
||||
|
||||
virtual ~Directive() { }
|
||||
|
||||
|
@ -106,9 +133,12 @@ public:
|
|||
|
||||
protected:
|
||||
Directive(SourceLocation DirectiveLoc, SourceLocation DiagnosticLoc,
|
||||
StringRef Text, unsigned Count)
|
||||
StringRef Text, unsigned Min, unsigned Max)
|
||||
: DirectiveLoc(DirectiveLoc), DiagnosticLoc(DiagnosticLoc),
|
||||
Text(Text), Count(Count) { }
|
||||
Text(Text), Min(Min), Max(Max) {
|
||||
assert(!DirectiveLoc.isInvalid() && "DirectiveLoc is invalid!");
|
||||
assert(!DiagnosticLoc.isInvalid() && "DiagnosticLoc is invalid!");
|
||||
}
|
||||
|
||||
private:
|
||||
Directive(const Directive&); // DO NOT IMPLEMENT
|
||||
|
|
|
@ -84,8 +84,8 @@ namespace {
|
|||
class StandardDirective : public Directive {
|
||||
public:
|
||||
StandardDirective(SourceLocation DirectiveLoc, SourceLocation DiagnosticLoc,
|
||||
StringRef Text, unsigned Count)
|
||||
: Directive(DirectiveLoc, DiagnosticLoc, Text, Count) { }
|
||||
StringRef Text, unsigned Min, unsigned Max)
|
||||
: Directive(DirectiveLoc, DiagnosticLoc, Text, Min, Max) { }
|
||||
|
||||
virtual bool isValid(std::string &Error) {
|
||||
// all strings are considered valid; even empty ones
|
||||
|
@ -102,8 +102,8 @@ public:
|
|||
class RegexDirective : public Directive {
|
||||
public:
|
||||
RegexDirective(SourceLocation DirectiveLoc, SourceLocation DiagnosticLoc,
|
||||
StringRef Text, unsigned Count)
|
||||
: Directive(DirectiveLoc, DiagnosticLoc, Text, Count), Regex(Text) { }
|
||||
StringRef Text, unsigned Min, unsigned Max)
|
||||
: Directive(DirectiveLoc, DiagnosticLoc, Text, Min, Max), Regex(Text) { }
|
||||
|
||||
virtual bool isValid(std::string &Error) {
|
||||
if (Regex.isValid(Error))
|
||||
|
@ -264,11 +264,29 @@ static void ParseDirective(const char *CommentStart, unsigned CommentLen,
|
|||
PH.SkipWhitespace();
|
||||
|
||||
// Next optional token: positive integer or a '+'.
|
||||
unsigned Count = 1;
|
||||
if (PH.Next(Count))
|
||||
unsigned Min = 1;
|
||||
unsigned Max = 1;
|
||||
if (PH.Next(Min)) {
|
||||
PH.Advance();
|
||||
else if (PH.Next("+")) {
|
||||
Count = Directive::OneOrMoreCount;
|
||||
// A positive integer can be followed by a '+' meaning min
|
||||
// or more, or by a '-' meaning a range from min to max.
|
||||
if (PH.Next("+")) {
|
||||
Max = Directive::MaxCount;
|
||||
PH.Advance();
|
||||
} else if (PH.Next("-")) {
|
||||
PH.Advance();
|
||||
if (!PH.Next(Max) || Max < Min) {
|
||||
Diags.Report(Pos.getLocWithOffset(PH.C-PH.Begin),
|
||||
diag::err_verify_invalid_range) << KindStr;
|
||||
continue;
|
||||
}
|
||||
PH.Advance();
|
||||
} else {
|
||||
Max = Min;
|
||||
}
|
||||
} else if (PH.Next("+")) {
|
||||
// '+' on its own means "1 or more".
|
||||
Max = Directive::MaxCount;
|
||||
PH.Advance();
|
||||
}
|
||||
|
||||
|
@ -308,7 +326,8 @@ static void ParseDirective(const char *CommentStart, unsigned CommentLen,
|
|||
Text.assign(ContentBegin, ContentEnd);
|
||||
|
||||
// Construct new directive.
|
||||
Directive *D = Directive::create(RegexKind, Pos, ExpectedLoc, Text, Count);
|
||||
Directive *D = Directive::create(RegexKind, Pos, ExpectedLoc, Text,
|
||||
Min, Max);
|
||||
std::string Error;
|
||||
if (D->isValid(Error))
|
||||
DL->push_back(D);
|
||||
|
@ -411,9 +430,8 @@ static unsigned CheckLists(DiagnosticsEngine &Diags, SourceManager &SourceMgr,
|
|||
for (DirectiveList::iterator I = Left.begin(), E = Left.end(); I != E; ++I) {
|
||||
Directive& D = **I;
|
||||
unsigned LineNo1 = SourceMgr.getPresumedLineNumber(D.DiagnosticLoc);
|
||||
bool FoundOnce = false;
|
||||
|
||||
for (unsigned i = 0; i < D.Count; ++i) {
|
||||
for (unsigned i = 0; i < D.Max; ++i) {
|
||||
DiagList::iterator II, IE;
|
||||
for (II = Right.begin(), IE = Right.end(); II != IE; ++II) {
|
||||
unsigned LineNo2 = SourceMgr.getPresumedLineNumber(II->first);
|
||||
|
@ -425,18 +443,12 @@ static unsigned CheckLists(DiagnosticsEngine &Diags, SourceManager &SourceMgr,
|
|||
break;
|
||||
}
|
||||
if (II == IE) {
|
||||
if (D.Count == D.OneOrMoreCount) {
|
||||
if (!FoundOnce)
|
||||
LeftOnly.push_back(*I);
|
||||
// We are only interested in at least one match, so exit the loop.
|
||||
break;
|
||||
}
|
||||
// Not found.
|
||||
if (i >= D.Min) break;
|
||||
LeftOnly.push_back(*I);
|
||||
} else {
|
||||
// Found. The same cannot be found twice.
|
||||
Right.erase(II);
|
||||
FoundOnce = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -527,8 +539,8 @@ VerifyDiagnosticConsumer::clone(DiagnosticsEngine &Diags) const {
|
|||
|
||||
Directive *Directive::create(bool RegexKind, SourceLocation DirectiveLoc,
|
||||
SourceLocation DiagnosticLoc, StringRef Text,
|
||||
unsigned Count) {
|
||||
unsigned Min, unsigned Max) {
|
||||
if (RegexKind)
|
||||
return new RegexDirective(DirectiveLoc, DiagnosticLoc, Text, Count);
|
||||
return new StandardDirective(DirectiveLoc, DiagnosticLoc, Text, Count);
|
||||
return new RegexDirective(DirectiveLoc, DiagnosticLoc, Text, Min, Max);
|
||||
return new StandardDirective(DirectiveLoc, DiagnosticLoc, Text, Min, Max);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue