[cfe-commits] [PATCH] Support for [[@LINE]], [[@LINE+<offset>]], [[@LINE-<offset>]] expressions in FileCheck
Alexander Kornienko
alexfh at google.com
Thu Nov 8 15:03:58 PST 2012
alexfh added you to the CC list for the revision "Support for [[@LINE]], [[@LINE+<offset>]], [[@LINE-<offset>]] expressions in FileCheck".
Hi chandlerc, gribozavr, doug.gregor,
Added support for [[@LINE]], [[@LINE+<offset>]], [[@LINE-<offset>]] expressions in FileCheck CHECK: lines.
This will help make many tests that rely on file line numbers less fragile. See tools/clang/test/Index/annotate-comments.cpp or tools/clang/test/Misc/caret-diags-macros.c, for a couple of examples.
http://llvm-reviews.chandlerc.com/D109
Files:
utils/FileCheck/FileCheck.cpp
Index: utils/FileCheck/FileCheck.cpp
===================================================================
--- utils/FileCheck/FileCheck.cpp
+++ utils/FileCheck/FileCheck.cpp
@@ -26,6 +26,7 @@
#include "llvm/Support/Signals.h"
#include "llvm/Support/system_error.h"
#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringMap.h"
#include <algorithm>
using namespace llvm;
@@ -63,6 +64,9 @@
/// RegEx - If non-empty, this is a regex pattern.
std::string RegExStr;
+ /// \brief Contains the number of line this pattern is in.
+ int LineNumber;
+
/// VariableUses - Entries in this vector map to uses of a variable in the
/// pattern, e.g. "foo[[bar]]baz". In this case, the RegExStr will contain
/// "foobaz" and we'll get an entry in this vector that tells us to insert the
@@ -79,7 +83,7 @@
Pattern(bool matchEOF = false) : MatchEOF(matchEOF) { }
- bool ParsePattern(StringRef PatternStr, SourceMgr &SM);
+ bool ParsePattern(StringRef PatternStr, SourceMgr &SM, int LineNumber);
/// Match - Match the pattern string against the input buffer Buffer. This
/// returns the position that is matched or npos if there is no match. If
@@ -104,10 +108,14 @@
/// should correspond to a perfect match.
unsigned ComputeMatchDistance(StringRef Buffer,
const StringMap<StringRef> &VariableTable) const;
+
+ bool EvaluateExpression(StringRef Expr, std::string &Value) const;
};
-bool Pattern::ParsePattern(StringRef PatternStr, SourceMgr &SM) {
+bool Pattern::ParsePattern(StringRef PatternStr, SourceMgr &SM,
+ int LineNumber) {
+ this->LineNumber = LineNumber;
PatternLoc = SMLoc::getFromPointer(PatternStr.data());
// Ignore trailing whitespace.
@@ -194,12 +202,19 @@
}
// Verify that the name is well formed.
- for (unsigned i = 0, e = Name.size(); i != e; ++i)
- if (Name[i] != '_' && !isalnum(Name[i])) {
+ bool IsExpression = false;
+ for (unsigned i = 0, e = Name.size(); i != e; ++i) {
+ if (i == 0 && Name[i] == '@') {
+ IsExpression = true;
+ continue;
+ }
+ if (Name[i] != '_' && !isalnum(Name[i]) &&
+ (!IsExpression || (Name[i] != '+' && Name[i] != '-'))) {
SM.PrintMessage(SMLoc::getFromPointer(Name.data()+i),
SourceMgr::DK_Error, "invalid name in named regex");
return true;
}
+ }
// Name can't start with a digit.
if (isdigit(Name[0])) {
@@ -279,6 +294,24 @@
return false;
}
+bool Pattern::EvaluateExpression(StringRef Expr, std::string &Value) const {
+ // The only supported expression is @LINE([\+-]\d+)?
+ if (!Expr.startswith("@LINE"))
+ return false;
+ Expr = Expr.substr(StringRef("@LINE").size());
+ int Offset = 0;
+ if (!Expr.empty()) {
+ if (Expr[0] == '+')
+ Expr = Expr.substr(1);
+ else if (Expr[0] != '-')
+ return false;
+ if (Expr.getAsInteger(10, Offset))
+ return false;
+ }
+ Value = llvm::itostr(LineNumber + Offset);
+ return true;
+}
+
/// Match - Match the pattern string against the input buffer Buffer. This
/// returns the position that is matched or npos if there is no match. If
/// there is a match, the size of the matched string is returned in MatchLen.
@@ -307,15 +340,21 @@
unsigned InsertOffset = 0;
for (unsigned i = 0, e = VariableUses.size(); i != e; ++i) {
- StringMap<StringRef>::iterator it =
- VariableTable.find(VariableUses[i].first);
- // If the variable is undefined, return an error.
- if (it == VariableTable.end())
- return StringRef::npos;
-
- // Look up the value and escape it so that we can plop it into the regex.
std::string Value;
- AddFixedStringToRegEx(it->second, Value);
+
+ if (VariableUses[i].first[0] == '@') {
+ if (!EvaluateExpression(VariableUses[i].first, Value))
+ return StringRef::npos;
+ } else {
+ StringMap<StringRef>::iterator it =
+ VariableTable.find(VariableUses[i].first);
+ // If the variable is undefined, return an error.
+ if (it == VariableTable.end())
+ return StringRef::npos;
+
+ // Look up the value and escape it so that we can plop it into the regex.
+ AddFixedStringToRegEx(it->second, Value);
+ }
// Plop it into the regex at the adjusted offset.
TmpStr.insert(TmpStr.begin()+VariableUses[i].second+InsertOffset,
@@ -371,19 +410,31 @@
// variable values.
if (!VariableUses.empty()) {
for (unsigned i = 0, e = VariableUses.size(); i != e; ++i) {
- StringRef Var = VariableUses[i].first;
- StringMap<StringRef>::const_iterator it = VariableTable.find(Var);
SmallString<256> Msg;
raw_svector_ostream OS(Msg);
-
- // Check for undefined variable references.
- if (it == VariableTable.end()) {
- OS << "uses undefined variable \"";
- OS.write_escaped(Var) << "\"";;
+ StringRef Var = VariableUses[i].first;
+ if (Var[0] == '@') {
+ std::string Value;
+ if (EvaluateExpression(Var, Value)) {
+ OS << "with expression \"";
+ OS.write_escaped(Var) << "\" equal to \"";
+ OS.write_escaped(Value) << "\"";
+ } else {
+ OS << "uses incorrect expression \"";
+ OS.write_escaped(Var) << "\"";
+ }
} else {
- OS << "with variable \"";
- OS.write_escaped(Var) << "\" equal to \"";
- OS.write_escaped(it->second) << "\"";
+ StringMap<StringRef>::const_iterator it = VariableTable.find(Var);
+
+ // Check for undefined variable references.
+ if (it == VariableTable.end()) {
+ OS << "uses undefined variable \"";
+ OS.write_escaped(Var) << "\"";
+ } else {
+ OS << "with variable \"";
+ OS.write_escaped(Var) << "\" equal to \"";
+ OS.write_escaped(it->second) << "\"";
+ }
}
SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), SourceMgr::DK_Note,
@@ -518,14 +569,20 @@
std::vector<std::pair<SMLoc, Pattern> > NotMatches;
+ int LineNumber = 1;
+
while (1) {
// See if Prefix occurs in the memory buffer.
- Buffer = Buffer.substr(Buffer.find(CheckPrefix));
-
+ size_t PrefixLoc = Buffer.find(CheckPrefix);
// If we didn't find a match, we're done.
- if (Buffer.empty())
+ if (PrefixLoc == StringRef::npos)
break;
+ // Recalculate line number.
+ LineNumber += Buffer.substr(0, PrefixLoc).count('\n');
+
+ Buffer = Buffer.substr(PrefixLoc);
+
const char *CheckPrefixStart = Buffer.data();
// When we find a check prefix, keep track of whether we find CHECK: or
@@ -560,7 +617,7 @@
// Parse the pattern.
Pattern P;
- if (P.ParsePattern(Buffer.substr(0, EOL), SM))
+ if (P.ParsePattern(Buffer.substr(0, EOL), SM, LineNumber))
return true;
Buffer = Buffer.substr(EOL);
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D109.1.patch
Type: text/x-patch
Size: 7036 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20121108/363b1f4d/attachment.bin>
More information about the cfe-commits
mailing list