llvm.org GIT mirror llvm / d976d43
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 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@188156 91177308-0d34-0410-b5e6-96231b3b80d8 Alexey Samsonov 6 years ago
3 changed file(s) with 94 addition(s) and 15 deletion(s). Raw diff Collapse all Expand all
5656
5757 class SpecialCaseList {
5858 public:
59 // FIXME: Switch all users to factories and remove these constructors.
5960 SpecialCaseList(const StringRef Path);
6061 SpecialCaseList(const MemoryBuffer *MB);
62
63 /// Parses the special case list from a file. If Path is empty, returns
64 /// an empty special case list. On failure, returns 0 and writes an error
65 /// message to string.
66 static SpecialCaseList *create(const StringRef Path, std::string &Error);
67 /// Parses the special case list from a memory buffer. On failure, returns
68 /// 0 and writes an error message to string.
69 static SpecialCaseList *create(const MemoryBuffer *MB, std::string &Error);
70
6171 ~SpecialCaseList();
6272
6373 /// Returns whether either this function or its source file are listed in the
8898 bool findCategory(const Module &M, StringRef &Category) const;
8999
90100 private:
101 SpecialCaseList(SpecialCaseList const &) LLVM_DELETED_FUNCTION;
102 SpecialCaseList &operator=(SpecialCaseList const &) LLVM_DELETED_FUNCTION;
103
91104 struct Entry;
92105 StringMap > Entries;
93106
94 void init(const MemoryBuffer *MB);
107 SpecialCaseList();
108 /// Parses just-constructed SpecialCaseList entries from a memory buffer.
109 bool parse(const MemoryBuffer *MB, std::string &Error);
110
95111 bool findCategory(const StringRef Section, const StringRef Query,
96112 StringRef &Category) const;
97113 bool inSectionCategory(const StringRef Section, const StringRef Query,
4848 }
4949 };
5050
51 SpecialCaseList::SpecialCaseList() : Entries() {}
52
5153 SpecialCaseList::SpecialCaseList(const StringRef Path) {
5254 // Validate and open blacklist file.
5355 if (Path.empty()) return;
5456 OwningPtr File;
5557 if (error_code EC = MemoryBuffer::getFile(Path, File)) {
56 report_fatal_error("Can't open blacklist file: " + Path + ": " +
58 report_fatal_error("Can't open file '" + Path + "': " +
5759 EC.message());
5860 }
5961
60 init(File.get());
62 std::string Error;
63 if (!parse(File.get(), Error))
64 report_fatal_error(Error);
6165 }
6266
6367 SpecialCaseList::SpecialCaseList(const MemoryBuffer *MB) {
64 init(MB);
65 }
66
67 void SpecialCaseList::init(const MemoryBuffer *MB) {
68 std::string Error;
69 if (!parse(MB, Error))
70 report_fatal_error(Error);
71 }
72
73 SpecialCaseList *SpecialCaseList::create(
74 const StringRef Path, std::string &Error) {
75 if (Path.empty())
76 return new SpecialCaseList();
77 OwningPtr File;
78 if (error_code EC = MemoryBuffer::getFile(Path, File)) {
79 Error = (Twine("Can't open file '") + Path + "': " + EC.message()).str();
80 return 0;
81 }
82 return create(File.get(), Error);
83 }
84
85 SpecialCaseList *SpecialCaseList::create(
86 const MemoryBuffer *MB, std::string &Error) {
87 OwningPtr SCL(new SpecialCaseList());
88 if (!SCL->parse(MB, Error))
89 return 0;
90 return SCL.take();
91 }
92
93 bool SpecialCaseList::parse(const MemoryBuffer *MB, std::string &Error) {
6894 // Iterate through each line in the blacklist file.
6995 SmallVector Lines;
7096 SplitString(MB->getBuffer(), Lines, "\n\r");
7197 StringMap > Regexps;
98 assert(Entries.empty() &&
99 "parse() should be called on an empty SpecialCaseList");
100 int LineNo = 1;
72101 for (SmallVectorImpl::iterator I = Lines.begin(), E = Lines.end();
73 I != E; ++I) {
102 I != E; ++I, ++LineNo) {
74103 // Ignore empty lines and lines starting with "#"
75104 if (I->empty() || I->startswith("#"))
76105 continue;
79108 StringRef Prefix = SplitLine.first;
80109 if (SplitLine.second.empty()) {
81110 // Missing ':' in the line.
82 report_fatal_error("malformed blacklist line: " + SplitLine.first);
111 Error = (Twine("Malformed line ") + Twine(LineNo) + ": '" +
112 SplitLine.first + "'").str();
113 return false;
83114 }
84115
85116 std::pair SplitRegexp = SplitLine.second.split("=");
112143
113144 // Check that the regexp is valid.
114145 Regex CheckRE(Regexp);
115 std::string Error;
116 if (!CheckRE.isValid(Error)) {
117 report_fatal_error("malformed blacklist regex: " + SplitLine.second +
118 ": " + Error);
146 std::string REError;
147 if (!CheckRE.isValid(REError)) {
148 Error = (Twine("Malformed regex in line ") + Twine(LineNo) + ": '" +
149 SplitLine.second + "': " + REError).str();
150 return false;
119151 }
120152
121153 // Add this regexp into the proper group by its prefix.
134166 Entries[I->getKey()][II->getKey()].RegEx = new Regex(II->getValue());
135167 }
136168 }
169 return true;
137170 }
138171
139172 SpecialCaseList::~SpecialCaseList() {
3333 M, ST, false, GlobalValue::ExternalLinkage, 0, Name);
3434 }
3535
36 SpecialCaseList *makeSpecialCaseList(StringRef List, std::string &Error) {
37 OwningPtr MB(MemoryBuffer::getMemBuffer(List));
38 return SpecialCaseList::create(MB.get(), Error);
39 }
40
3641 SpecialCaseList *makeSpecialCaseList(StringRef List) {
37 OwningPtr MB(MemoryBuffer::getMemBuffer(List));
38 return new SpecialCaseList(MB.get());
42 std::string Error;
43 SpecialCaseList *SCL = makeSpecialCaseList(List, Error);
44 assert(SCL);
45 assert(Error == "");
46 return SCL;
3947 }
4048
4149 LLVMContext Ctx;
154162 EXPECT_TRUE(SCL->isIn(*F));
155163 }
156164
165 TEST_F(SpecialCaseListTest, InvalidSpecialCaseList) {
166 std::string Error;
167 EXPECT_EQ(0, makeSpecialCaseList("badline", Error));
168 EXPECT_EQ("Malformed line 1: 'badline'", Error);
169 EXPECT_EQ(0, makeSpecialCaseList("src:bad[a-", Error));
170 EXPECT_EQ("Malformed regex in line 1: 'bad[a-': invalid character range",
171 Error);
172 EXPECT_EQ(0, makeSpecialCaseList("src:a.c\n"
173 "fun:fun(a\n",
174 Error));
175 EXPECT_EQ("Malformed regex in line 2: 'fun(a': parentheses not balanced",
176 Error);
177 EXPECT_EQ(0, SpecialCaseList::create("unexisting", Error));
178 EXPECT_EQ("Can't open file 'unexisting': No such file or directory", Error);
157179 }
180
181 TEST_F(SpecialCaseListTest, EmptySpecialCaseList) {
182 OwningPtr SCL(makeSpecialCaseList(""));
183 Module M("foo", Ctx);
184 EXPECT_FALSE(SCL->isIn(M));
185 }
186
187 }