diff --git a/clang/include/clang/Frontend/CompilerInvocation.h b/clang/include/clang/Frontend/CompilerInvocation.h --- a/clang/include/clang/Frontend/CompilerInvocation.h +++ b/clang/include/clang/Frontend/CompilerInvocation.h @@ -185,7 +185,19 @@ /// identifying the conditions under which the module was built. std::string getModuleHash() const; - std::string getCC1CommandLine() const; + /// Generate a cc1-compatible command line arguments from this instance. + /// + /// \param [out] Args - The generated arguments. Note that the caller is + /// responsible for insersting the path to the clang executable and "-cc1" if + /// desired. + /// \param StringAllocator - A function that given a Twine can allocate + /// storage for a given command line argument and return a pointer to the + /// newly allocated string. The returned pointer is what gets appended to + /// Args. + void + generateCC1CommandLine(llvm::SmallVectorImpl &Args, + llvm::function_ref + StringAllocator) const; /// @} /// @name Option Subgroups diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -51,6 +51,7 @@ #include "llvm/ADT/Hashing.h" #include "llvm/ADT/None.h" #include "llvm/ADT/Optional.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" @@ -3831,9 +3832,9 @@ return llvm::APInt(64, code).toString(36, /*Signed=*/false); } -std::string CompilerInvocation::getCC1CommandLine() const { - std::string CMDLine; - llvm::raw_string_ostream CMDStream(CMDLine); +void CompilerInvocation::generateCC1CommandLine( + SmallVectorImpl &Args, + llvm::function_ref StringAllocator) const { #define PREFIX(PREFIX_TYPE, BRACED_INIT) \ const char *PREFIX_TYPE[4] = BRACED_INIT; #define OPTION_WITH_MARSHALLING(PREFIX_TYPE, NAME, ID, KIND, GROUP, ALIAS, \ @@ -3841,11 +3842,10 @@ VALUES, KEYPATH, IS_POSITIVE, DEFAULT_VALUE) \ if (Option::KIND##Class == Option::FlagClass && \ IS_POSITIVE != DEFAULT_VALUE && this->KEYPATH != DEFAULT_VALUE) \ - CMDStream << " " << PREFIX_TYPE[0] << NAME; + Args.push_back(StringAllocator(Twine(PREFIX_TYPE[0]) + NAME)); #include "clang/Driver/Options.inc" #undef OPTION_WITH_MARSHALLING #undef PREFIX - return CMDStream.str(); } namespace clang { diff --git a/clang/unittests/Frontend/CompilerInvocationTest.cpp b/clang/unittests/Frontend/CompilerInvocationTest.cpp --- a/clang/unittests/Frontend/CompilerInvocationTest.cpp +++ b/clang/unittests/Frontend/CompilerInvocationTest.cpp @@ -24,7 +24,15 @@ CompilerInvocation CInvok; CompilerInvocation::CreateFromArgs(CInvok, Args, *Diags); - ASSERT_EQ(CInvok.getCC1CommandLine(), " -fmodules-strict-context-hash"); + SmallVector GeneratedArgs; + SmallVector GeneratedArgsStorage; + auto StringAlloc = [&GeneratedArgsStorage](const Twine &Arg) { + return GeneratedArgsStorage.emplace_back(Arg.str()).c_str(); + }; + + CInvok.generateCC1CommandLine(GeneratedArgs, StringAlloc); + + ASSERT_STREQ(GeneratedArgs[0], "-fmodules-strict-context-hash"); } } // anonymous namespace