[PATCH] Introduce factory methods for SpecialCaseList

Alexey Samsonov samsonov at google.com
Fri Aug 9 01:28:44 PDT 2013


  Address comments by pcc

Hi pcc,

http://llvm-reviews.chandlerc.com/D1327

CHANGE SINCE LAST DIFF
  http://llvm-reviews.chandlerc.com/D1327?vs=3288&id=3312#toc

Files:
  unittests/Transforms/Utils/SpecialCaseList.cpp
  lib/Transforms/Utils/SpecialCaseList.cpp
  include/llvm/Transforms/Utils/SpecialCaseList.h

Index: unittests/Transforms/Utils/SpecialCaseList.cpp
===================================================================
--- unittests/Transforms/Utils/SpecialCaseList.cpp
+++ unittests/Transforms/Utils/SpecialCaseList.cpp
@@ -34,9 +34,17 @@
         M, ST, false, GlobalValue::ExternalLinkage, 0, Name);
   }
 
-  SpecialCaseList *makeSpecialCaseList(StringRef List) {
+  SpecialCaseList *makeSpecialCaseList(StringRef List, std::string &Error) {
     OwningPtr<MemoryBuffer> MB(MemoryBuffer::getMemBuffer(List));
-    return new SpecialCaseList(MB.get());
+    return SpecialCaseList::create(MB.get(), Error);
+  }
+
+  SpecialCaseList *makeSpecialCaseList(StringRef List) {
+    std::string Error;
+    SpecialCaseList *SCL = makeSpecialCaseList(List, Error);
+    assert(SCL);
+    assert(Error == "");
+    return SCL;
   }
 
   LLVMContext Ctx;
@@ -155,4 +163,26 @@
   EXPECT_TRUE(SCL->isIn(*F));
 }
 
+TEST_F(SpecialCaseListTest, InvalidSpecialCaseList) {
+  std::string Error;
+  EXPECT_EQ(0, makeSpecialCaseList("badline", Error));
+  EXPECT_EQ("Malformed line 1: 'badline'", Error);
+  EXPECT_EQ(0, makeSpecialCaseList("src:bad[a-", Error));
+  EXPECT_EQ("Malformed regex in line 1: 'bad[a-': invalid character range",
+            Error);
+  EXPECT_EQ(0, makeSpecialCaseList("src:a.c\n"
+                                   "fun:fun(a\n",
+                                   Error));
+  EXPECT_EQ("Malformed regex in line 2: 'fun(a': parentheses not balanced",
+            Error);
+  EXPECT_EQ(0, SpecialCaseList::create("unexisting", Error));
+  EXPECT_EQ("Can't open file 'unexisting': No such file or directory", Error);
+}
+
+TEST_F(SpecialCaseListTest, EmptySpecialCaseList) {
+  OwningPtr<SpecialCaseList> SCL(makeSpecialCaseList(""));
+  Module M("foo", Ctx);
+  EXPECT_FALSE(SCL->isIn(M));
+}
+
 }
Index: lib/Transforms/Utils/SpecialCaseList.cpp
===================================================================
--- lib/Transforms/Utils/SpecialCaseList.cpp
+++ lib/Transforms/Utils/SpecialCaseList.cpp
@@ -49,38 +49,69 @@
   }
 };
 
+SpecialCaseList::SpecialCaseList() : Entries() {}
+
 SpecialCaseList::SpecialCaseList(const StringRef Path) {
   // Validate and open blacklist file.
   if (Path.empty()) return;
   OwningPtr<MemoryBuffer> File;
   if (error_code EC = MemoryBuffer::getFile(Path, File)) {
-    report_fatal_error("Can't open blacklist file: " + Path + ": " +
+    report_fatal_error("Can't open file '" + Path + "': " +
                        EC.message());
   }
 
-  init(File.get());
+  std::string Error;
+  if (!parse(File.get(), Error))
+    report_fatal_error(Error);
 }
 
 SpecialCaseList::SpecialCaseList(const MemoryBuffer *MB) {
-  init(MB);
+  std::string Error;
+  if (!parse(MB, Error))
+    report_fatal_error(Error);
 }
 
-void SpecialCaseList::init(const MemoryBuffer *MB) {
+SpecialCaseList *SpecialCaseList::create(
+    const StringRef Path, std::string &Error) {
+  if (Path.empty())
+    return new SpecialCaseList();
+  OwningPtr<MemoryBuffer> File;
+  if (error_code EC = MemoryBuffer::getFile(Path, File)) {
+    Error = (Twine("Can't open file '") + Path + "': " + EC.message()).str();
+    return 0;
+  }
+  return create(File.get(), Error);
+}
+
+SpecialCaseList *SpecialCaseList::create(
+    const MemoryBuffer *MB, std::string &Error) {
+  OwningPtr<SpecialCaseList> SCL(new SpecialCaseList());
+  if (!SCL->parse(MB, Error))
+    return 0;
+  return SCL.take();
+}
+
+bool SpecialCaseList::parse(const MemoryBuffer *MB, std::string &Error) {
   // Iterate through each line in the blacklist file.
   SmallVector<StringRef, 16> Lines;
   SplitString(MB->getBuffer(), Lines, "\n\r");
   StringMap<StringMap<std::string> > Regexps;
+  assert(Entries.empty() &&
+         "parse() should be called on an empty SpecialCaseList");
+  int LineNo = 1;
   for (SmallVectorImpl<StringRef>::iterator I = Lines.begin(), E = Lines.end();
-       I != E; ++I) {
+       I != E; ++I, ++LineNo) {
     // Ignore empty lines and lines starting with "#"
     if (I->empty() || I->startswith("#"))
       continue;
     // Get our prefix and unparsed regexp.
     std::pair<StringRef, StringRef> SplitLine = I->split(":");
     StringRef Prefix = SplitLine.first;
     if (SplitLine.second.empty()) {
       // Missing ':' in the line.
-      report_fatal_error("malformed blacklist line: " + SplitLine.first);
+      Error = (Twine("Malformed line ") + Twine(LineNo) + ": '" +
+               SplitLine.first + "'").str();
+      return false;
     }
 
     std::pair<StringRef, StringRef> SplitRegexp = SplitLine.second.split("=");
@@ -113,10 +144,11 @@
 
     // Check that the regexp is valid.
     Regex CheckRE(Regexp);
-    std::string Error;
-    if (!CheckRE.isValid(Error)) {
-      report_fatal_error("malformed blacklist regex: " + SplitLine.second +
-          ": " + Error);
+    std::string REError;
+    if (!CheckRE.isValid(REError)) {
+      Error = (Twine("Malformed regex in line ") + Twine(LineNo) + ": '" +
+               SplitLine.second + "': " + REError).str();
+      return false;
     }
 
     // Add this regexp into the proper group by its prefix.
@@ -135,6 +167,7 @@
       Entries[I->getKey()][II->getKey()].RegEx = new Regex(II->getValue());
     }
   }
+  return true;
 }
 
 SpecialCaseList::~SpecialCaseList() {
Index: include/llvm/Transforms/Utils/SpecialCaseList.h
===================================================================
--- include/llvm/Transforms/Utils/SpecialCaseList.h
+++ include/llvm/Transforms/Utils/SpecialCaseList.h
@@ -57,8 +57,18 @@
 
 class SpecialCaseList {
  public:
+  // FIXME: Switch all users to factories and remove these constructors.
   SpecialCaseList(const StringRef Path);
   SpecialCaseList(const MemoryBuffer *MB);
+
+  /// Parses the special case list from a file. If Path is empty, returns
+  /// an empty special case list. On failure, returns 0 and writes an error
+  /// message to string.
+  static SpecialCaseList *create(const StringRef Path, std::string &Error);
+  /// Parses the special case list from a memory buffer. On failure, returns
+  /// 0 and writes an error message to string.
+  static SpecialCaseList *create(const MemoryBuffer *MB, std::string &Error);
+
   ~SpecialCaseList();
 
   /// Returns whether either this function or its source file are listed in the
@@ -89,10 +99,16 @@
   bool findCategory(const Module &M, StringRef &Category) const;
 
  private:
+  SpecialCaseList(SpecialCaseList const &) LLVM_DELETED_FUNCTION;
+  SpecialCaseList &operator=(SpecialCaseList const &) LLVM_DELETED_FUNCTION;
+
   struct Entry;
   StringMap<StringMap<Entry> > Entries;
 
-  void init(const MemoryBuffer *MB);
+  SpecialCaseList();
+  /// Parses just-constructed SpecialCaseList entries from a memory buffer.
+  bool parse(const MemoryBuffer *MB, std::string &Error);
+
   bool findCategory(const StringRef Section, const StringRef Query,
                     StringRef &Category) const;
   bool inSectionCategory(const StringRef Section, const StringRef Query,
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D1327.2.patch
Type: text/x-patch
Size: 7009 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20130809/7c0a7182/attachment.bin>


More information about the llvm-commits mailing list