[llvm] r188156 - Introduce factory methods for SpecialCaseList
Alexey Samsonov
samsonov at google.com
Mon Aug 12 00:49:36 PDT 2013
Author: samsonov
Date: Mon Aug 12 02:49:36 2013
New Revision: 188156
URL: http://llvm.org/viewvc/llvm-project?rev=188156&view=rev
Log:
Introduce factory methods for SpecialCaseList
Summary:
Doing work in constructors is bad: this change suggests to
call SpecialCaseList::create(Path, Error) instead of
"new SpecialCaseList(Path)". Currently the latter may crash with
report_fatal_error, which is undesirable - sometimes we want to report
the error to user gracefully - for example, if he provides an incorrect
file as an argument of Clang's -fsanitize-blacklist flag.
Reviewers: pcc
Reviewed By: pcc
CC: llvm-commits
Differential Revision: http://llvm-reviews.chandlerc.com/D1327
Modified:
llvm/trunk/include/llvm/Transforms/Utils/SpecialCaseList.h
llvm/trunk/lib/Transforms/Utils/SpecialCaseList.cpp
llvm/trunk/unittests/Transforms/Utils/SpecialCaseList.cpp
Modified: llvm/trunk/include/llvm/Transforms/Utils/SpecialCaseList.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Transforms/Utils/SpecialCaseList.h?rev=188156&r1=188155&r2=188156&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Transforms/Utils/SpecialCaseList.h (original)
+++ llvm/trunk/include/llvm/Transforms/Utils/SpecialCaseList.h Mon Aug 12 02:49:36 2013
@@ -57,8 +57,18 @@ class StringRef;
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 @@ class SpecialCaseList {
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,
Modified: llvm/trunk/lib/Transforms/Utils/SpecialCaseList.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/SpecialCaseList.cpp?rev=188156&r1=188155&r2=188156&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Utils/SpecialCaseList.cpp (original)
+++ llvm/trunk/lib/Transforms/Utils/SpecialCaseList.cpp Mon Aug 12 02:49:36 2013
@@ -49,29 +49,58 @@ struct SpecialCaseList::Entry {
}
};
+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;
@@ -80,7 +109,9 @@ void SpecialCaseList::init(const MemoryB
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 @@ void SpecialCaseList::init(const MemoryB
// 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 @@ void SpecialCaseList::init(const MemoryB
Entries[I->getKey()][II->getKey()].RegEx = new Regex(II->getValue());
}
}
+ return true;
}
SpecialCaseList::~SpecialCaseList() {
Modified: llvm/trunk/unittests/Transforms/Utils/SpecialCaseList.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/Transforms/Utils/SpecialCaseList.cpp?rev=188156&r1=188155&r2=188156&view=diff
==============================================================================
--- llvm/trunk/unittests/Transforms/Utils/SpecialCaseList.cpp (original)
+++ llvm/trunk/unittests/Transforms/Utils/SpecialCaseList.cpp Mon Aug 12 02:49:36 2013
@@ -34,9 +34,17 @@ protected:
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 @@ TEST_F(SpecialCaseListTest, Substring) {
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));
+}
+
}
More information about the llvm-commits
mailing list