llvm.org GIT mirror llvm / 855d602
Revert "[Support] Promote cl::StringSaver to a separate utility" This reverts commit r215784 / 3f8a26f6fe16cc76c98ab21db2c600bd7defbbaa. LLD has 3 StringSaver's, one of which takes a lock when saving the string... Need to investigate more closely. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@215790 91177308-0d34-0410-b5e6-96231b3b80d8 Sean Silva 6 years ago
4 changed file(s) with 45 addition(s) and 43 deletion(s). Raw diff Collapse all Expand all
2323 #include "llvm/ADT/StringMap.h"
2424 #include "llvm/ADT/Twine.h"
2525 #include "llvm/Support/Compiler.h"
26 #include "llvm/Support/StringSaver.h"
2726 #include
2827 #include
2928 #include
17721771 // Standalone command line processing utilities.
17731772 //
17741773
1774 /// \brief Saves strings in the inheritor's stable storage and returns a stable
1775 /// raw character pointer.
1776 class StringSaver {
1777 virtual void anchor();
1778 public:
1779 virtual const char *SaveString(const char *Str) = 0;
1780 virtual ~StringSaver() {}; // Pacify -Wnon-virtual-dtor.
1781 };
1782
17751783 /// \brief Tokenizes a command line that can contain escapes and quotes.
17761784 //
17771785 /// The quoting rules match those used by GCC and other tools that use
+0
-33
include/llvm/Support/StringSaver.h less more
None //===- llvm/Support/StringSaver.h - Stable storage for strings --*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8
9 #ifndef LLVM_SUPPORT_STRINGSAVER_H
10 #define LLVM_SUPPORT_STRINGSAVER_H
11
12 #include "llvm/Support/Allocator.h"
13 #include
14
15 namespace llvm {
16
17 /// \brief Saves strings in stable storage that it owns.
18 class StringSaver {
19 BumpPtrAllocator Alloc;
20
21 public:
22 const char *saveCStr(const char *CStr) {
23 auto Len = std::strlen(CStr) + 1; // Don't forget the NUL!
24 char *Buf = Alloc.Allocate(Len);
25 std::memcpy(Buf, CStr, Len);
26 return Buf;
27 }
28 };
29
30 } // end namespace llvm
31
32 #endif
7575 void parser::anchor() {}
7676 void parser::anchor() {}
7777 void parser::anchor() {}
78 void StringSaver::anchor() {}
7879
7980 //===----------------------------------------------------------------------===//
8081
507508 // End the token if this is whitespace.
508509 if (isWhitespace(Src[I])) {
509510 if (!Token.empty())
510 NewArgv.push_back(Saver.saveCStr(Token.c_str()));
511 NewArgv.push_back(Saver.SaveString(Token.c_str()));
511512 Token.clear();
512513 continue;
513514 }
518519
519520 // Append the last token after hitting EOF with no whitespace.
520521 if (!Token.empty())
521 NewArgv.push_back(Saver.saveCStr(Token.c_str()));
522 NewArgv.push_back(Saver.SaveString(Token.c_str()));
522523 }
523524
524525 /// Backslashes are interpreted in a rather complicated way in the Windows-style
591592 if (State == UNQUOTED) {
592593 // Whitespace means the end of the token.
593594 if (isWhitespace(Src[I])) {
594 NewArgv.push_back(Saver.saveCStr(Token.c_str()));
595 NewArgv.push_back(Saver.SaveString(Token.c_str()));
595596 Token.clear();
596597 State = INIT;
597598 continue;
623624 }
624625 // Append the last token after hitting EOF with no whitespace.
625626 if (!Token.empty())
626 NewArgv.push_back(Saver.saveCStr(Token.c_str()));
627 NewArgv.push_back(Saver.SaveString(Token.c_str()));
627628 }
628629
629630 static bool ExpandResponseFile(const char *FName, StringSaver &Saver,
689690 return AllExpanded;
690691 }
691692
693 namespace {
694 class StrDupSaver : public StringSaver {
695 std::vector Dups;
696 public:
697 ~StrDupSaver() {
698 for (std::vector::iterator I = Dups.begin(), E = Dups.end();
699 I != E; ++I) {
700 char *Dup = *I;
701 free(Dup);
702 }
703 }
704 const char *SaveString(const char *Str) override {
705 char *Dup = strdup(Str);
706 Dups.push_back(Dup);
707 return Dup;
708 }
709 };
710 }
711
692712 /// ParseEnvironmentOptions - An alternative entry point to the
693713 /// CommandLine library, which allows you to read the program's name
694714 /// from the caller (as PROGNAME) and its command-line arguments from
708728 // Get program's "name", which we wouldn't know without the caller
709729 // telling us.
710730 SmallVector newArgv;
711 StringSaver Saver;
712 newArgv.push_back(Saver.saveCStr(progName));
731 StrDupSaver Saver;
732 newArgv.push_back(Saver.SaveString(progName));
713733
714734 // Parse the value of the environment variable into a "command line"
715735 // and hand it off to ParseCommandLineOptions().
733753 SmallVector newArgv;
734754 for (int i = 0; i != argc; ++i)
735755 newArgv.push_back(argv[i]);
736 StringSaver Saver;
756 StrDupSaver Saver;
737757 ExpandResponseFiles(Saver, TokenizeGNUCommandLine, newArgv);
738758 argv = &newArgv[0];
739759 argc = static_cast(newArgv.size());
145145 "Category.";
146146 }
147147
148 typedef void ParserFunction(StringRef Source, StringSaver &Saver,
148 class StrDupSaver : public cl::StringSaver {
149 const char *SaveString(const char *Str) override {
150 return strdup(Str);
151 }
152 };
153
154 typedef void ParserFunction(StringRef Source, llvm::cl::StringSaver &Saver,
149155 SmallVectorImpl &NewArgv);
150156
151157
152158 void testCommandLineTokenizer(ParserFunction *parse, const char *Input,
153159 const char *const Output[], size_t OutputSize) {
154160 SmallVector Actual;
155 StringSaver Saver;
161 StrDupSaver Saver;
156162 parse(Input, Saver, Actual);
157163 EXPECT_EQ(OutputSize, Actual.size());
158164 for (unsigned I = 0, E = Actual.size(); I != E; ++I) {
159165 if (I < OutputSize)
160166 EXPECT_STREQ(Output[I], Actual[I]);
167 free(const_cast(Actual[I]));
161168 }
162169 }
163170